{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Compress_attn"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [],
   "source": [
    "import torch\n",
    "import triton\n",
    "import math\n",
    "from copy import deepcopy\n",
    "import os\n",
    "os.environ['TRITON_PRINT_AUTOTUNING'] = '1'\n",
    "from torch_code import torch_blcok_compress, torch_cmp_attn, flex_cmp_attn\n",
    "from compress_attn import blcok_compress as triton_block_compress\n",
    "from compress_attn import compress_attn as triton_compress_attn_v1\n",
    "from compress_attn_v2 import compress_attn as triton_compress_attn_v2\n",
    "from transformers import LlamaForCausalLM"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## block_compress\n",
    "- 目前这个版本weight是[kernel_size], pe是[kernel_size, v_head_dim / k_head_dim]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 精度"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "================================================== forward output:\n",
      "torch   bf16 vs torch fp32: 最大差值: 0.20862579345703125, 平均差值: 0.022884361445903778\n",
      "triton  bf16 vs torch fp32: 最大差值: 0.12482452392578125, 平均差值: 0.01120144035667181\n",
      "================================================== backward input grad:\n",
      "torch   bf16 vs torch fp32: 最大差值: 0.01727294921875, 平均差值: 0.00157164316624403\n",
      "triton  bf16 vs torch fp32: 最大差值: 0.0078125, 平均差值: 0.0010277547407895327\n",
      "================================================== backward weight grad:\n",
      "torch   bf16 vs torch fp32: 最大差值: 56.013671875, 平均差值: 8.716752052307129\n",
      "triton  bf16 vs torch fp32: 最大差值: 56.013671875, 平均差值: 8.567572593688965\n",
      "================================================== backward pe grad:\n",
      "torch   bf16 vs torch fp32: 最大差值: 4.180908203125, 平均差值: 0.731353759765625\n",
      "triton  bf16 vs torch fp32: 最大差值: 3.99853515625, 平均差值: 0.7305139303207397\n"
     ]
    }
   ],
   "source": [
    "device = 'cuda'\n",
    "dtype = torch.bfloat16\n",
    "# 论文中k的配置\n",
    "b, h, n, d = 1, 4, 4096, 192\n",
    "stride = 16\n",
    "kernel_size = 32\n",
    "x1 = torch.randn(b, n, h, d, device=device, dtype=dtype)\n",
    "x1.requires_grad_(True)\n",
    "weight1 = torch.nn.Parameter(torch.randn(kernel_size, device=device, dtype=dtype))\n",
    "pe1 = torch.nn.Parameter(torch.randn(kernel_size, d, device=device, dtype=dtype))\n",
    "x2 = deepcopy(x1)\n",
    "weight2 = deepcopy(weight1)\n",
    "pe2 = deepcopy(pe1)\n",
    "x3 = torch.randn(b, n, h, d, device=device, dtype=torch.float32)\n",
    "x3.requires_grad_(True)\n",
    "weight3 = torch.nn.Parameter(torch.randn(kernel_size, device=device, dtype=torch.float32))\n",
    "pe3 = torch.nn.Parameter(torch.randn(kernel_size, d, device=device, dtype=torch.float32))\n",
    "x3.data.copy_(x1.data)\n",
    "weight3.data.copy_(weight1.data)\n",
    "pe3.data.copy_(pe1.data)\n",
    "\n",
    "y1 = torch_blcok_compress(x1, weight1, pe1, stride)\n",
    "y2 = triton_block_compress(x2, weight2, pe2, stride)\n",
    "y3 = torch_blcok_compress(x3, weight3, pe3, stride)\n",
    "dy = torch.rand_like(y1)\n",
    "y1.backward(dy)\n",
    "y2.backward(dy)\n",
    "y3.backward(dy.float())\n",
    "print('='*50 + ' forward output:')\n",
    "print(f'torch   bf16 vs torch fp32: 最大差值: {(y1-y3).abs().max().item()}, 平均差值: {(y1-y3).abs().mean().item()}')\n",
    "print(f'triton  bf16 vs torch fp32: 最大差值: {(y2-y3).abs().max().item()}, 平均差值: {(y2-y3).abs().mean().item()}')\n",
    "print('='*50 + ' backward input grad:')\n",
    "print(f'torch   bf16 vs torch fp32: 最大差值: {(x1.grad-x3.grad).abs().max().item()}, 平均差值: {(x1.grad-x3.grad).abs().mean().item()}')\n",
    "print(f'triton  bf16 vs torch fp32: 最大差值: {(x2.grad-x3.grad).abs().max().item()}, 平均差值: {(x2.grad-x3.grad).abs().mean().item()}')\n",
    "print('='*50 + ' backward weight grad:')\n",
    "print(f'torch   bf16 vs torch fp32: 最大差值: {(weight1.grad-weight3.grad).abs().max().item()}, 平均差值: {(weight1.grad-weight3.grad).abs().mean().item()}')\n",
    "print(f'triton  bf16 vs torch fp32: 最大差值: {(weight2.grad-weight3.grad).abs().max().item()}, 平均差值: {(weight2.grad-weight3.grad).abs().mean().item()}')\n",
    "print('='*50 + ' backward pe grad:')\n",
    "print(f'torch   bf16 vs torch fp32: 最大差值: {(pe1.grad-pe3.grad).abs().max().item()}, 平均差值: {(pe1.grad-pe3.grad).abs().mean().item()}')\n",
    "print(f'triton  bf16 vs torch fp32: 最大差值: {(pe2.grad-pe3.grad).abs().max().item()}, 平均差值: {(pe2.grad-pe3.grad).abs().mean().item()}')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### forward"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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+O6774SZmZn473//q1mH3xFli+WmhCIjIwWAVx6+vr5CiLxL/WbMmCHs7OyEQqEQ3bp1Ezdu3Mj3Go8fPxYDBgwQ5ubmwtLSUgwePFikpKTkW+fixYvinXfeEQqFQtSqVUssXLjwlSy7du0SjRo1EsbGxqJZs2Zi//79Zfa5S6ugfQZAbN68WbNORkaGGDlypKhataowMzMTffv2FQ8fPsz3On///bfo0aOHMDU1FTY2NmL8+PEiJycn3zqRkZHC2dlZGBsbi7feeivfezy3evVqUadOHWFsbCzc3NzEqVOnyuJjl9qXX34p6tatK4yNjUWNGjVEt27dNMVGCO6z4nq53HD/Fax///7CwcFBGBsbi1q1aon+/fvnu1cL91vhfvnlF9G8eXOhUChEkyZNxPr16/M9z++IsiUTQghpjhkRERERaR/H3BAREZFeYbkhIiIivcJyQ0RERHqF5YaIiIj0CssNERER6RWWGyIiItIrLDdERESkV1huiIiISK+w3BAREZFeYbkhIiIivcJyQ0RERHrFUOoARESl1blzZ7Rs2RImJibYuHEjjI2N4efnh1mzZkkdjYgkwCM3RKQXtm7diipVquD06dNYvHgx5syZg8OHD0sdi4gkwFnBiajC69y5M1QqFU6cOKFZ5ubmhq5du2LhwoUSJiMiKfDIDRHphZYtW+b73cHBAYmJiRKlISIpsdwQkV4wMjLK97tMJoNarZYoDRFJieWGiIiI9ArLDREREekVlhsiIiLSK7xaioiIiPQKj9wQERGRXmG5ISIiIr3CckNERER6heWGiIiI9ArLDREREekVlhsiIiLSKyw3REREpFdYboiIiEivsNwQERGRXmG5ISIiIr3CckNERER65f8Bn4xRSnqu9YwAAAAASUVORK5CYII=",
      "text/plain": [
       "<Figure size 640x480 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "forward:\n",
      "         n    Triton     Torch\n",
      "0   8192.0  0.018637  0.145369\n",
      "1  16384.0  0.030112  0.275428\n",
      "2  24576.0  0.040990  0.412948\n",
      "3  32768.0  0.052366  0.535446\n",
      "4  40960.0  0.062871  0.658381\n",
      "5  49152.0  0.074192  0.776901\n",
      "6  57344.0  0.085014  0.897856\n",
      "7  65536.0  0.095806  1.017664\n"
     ]
    }
   ],
   "source": [
    "torch.cuda.empty_cache()\n",
    "@triton.testing.perf_report(\n",
    "    triton.testing.Benchmark(\n",
    "        x_names=['n'],  # argument names to use as an x-axis for the plot\n",
    "        x_vals=[8192 * i for i in range(1, 8+1)],  # different possible values for `x_name`\n",
    "        line_arg='provider',  # argument name whose value corresponds to a different line in the plot\n",
    "        line_vals=['triton', 'torch'],  # possible values for `line_arg``\n",
    "        line_names=[\n",
    "            \"Triton\",\n",
    "            \"Torch\",\n",
    "        ],  # label name for the lines\n",
    "        styles=[('blue', '-'), ('green', '-')],  # line styles\n",
    "        ylabel=\"ms\",  # label name for the y-axis\n",
    "        plot_name=\"forward\",  # name for the plot. Used also as a file name for saving the plot.\n",
    "        args={'b':1, 'h':4, 'd':128, 'stride':16, 'kernel_size':32},  # values for function arguments not in `x_names` and `y_name`\n",
    "    ))\n",
    "def benchmark(b, provider, h, n, d, stride, kernel_size):\n",
    "    device = 'cuda'\n",
    "    dtype = torch.bfloat16\n",
    "    x = torch.randn(b, n, h, d, device=device, dtype=dtype)\n",
    "    weight = torch.nn.Parameter(torch.randn(kernel_size, device=device, dtype=dtype))\n",
    "    pe = torch.nn.Parameter(torch.randn(kernel_size, d, device=device, dtype=dtype))\n",
    "\n",
    "    stream = torch.cuda.Stream()\n",
    "    torch.cuda.set_stream(stream)\n",
    "    if provider == 'torch':\n",
    "        ms = triton.testing.do_bench(lambda: torch_blcok_compress(x, weight, pe, stride))\n",
    "    if provider == 'triton':\n",
    "        ms = triton.testing.do_bench(lambda: triton_block_compress(x, weight, pe, stride))\n",
    "    return ms\n",
    "benchmark.run(show_plots=True, print_data=True)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### backward"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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zzgGKB8lNQYoR5MDU5kpByYTERGVAI4B0lOcF4uIiEg/cDQtERERGR0GICIiIjI6DEBERERkdBiAiIiIyOgwABEREZHRYQAiIiIio8MAREREREaHAYiIiIiMDgMQERERGR0GICIiIjI6DEBERERkdBiAiIiIyOgwABEREZHRYQAiIiIio8MAREREREaHAYiIiIiMDgMQERERGR0GICIiIjI6DEBERERkdBiAiIiIyOgwABEREZHRYQAiIiIio8MAREREREaHAYiIiIiMDgMQERERGR0GICIiIjI6DEBERERkdBiAiIiIyOgwABEREZHRYQAiIiIio8MAREREREZHLwJQcHAw3N3dYWlpCR8fH5w+fbrAtqtXr0abNm1gZ2cHOzs7+Pn55Wk/aNAgyGQynaVTp04lfRhERERkICQPQFu3bkVAQABmzpyJf/75B15eXvD390d8fHy+7cPDw9GvXz8cOXIEERERcHNzQ8eOHfHo0SOddp06dUJMTIx22bx5c2kcDhERERkAmRBCSFmAj48PmjVrhuXLlwMANBoN3NzcMG7cOEydOvWl71er1bCzs8Py5cvx6aefAsjtAUpKSsLOnTuLVJNSqYRCoUBycjJsbGyKtA8iIiIqXa/z/S1pD1BWVhbOnTsHPz8/7ToTExP4+fkhIiLilfaRnp6O7Oxs2Nvb66wPDw+Ho6MjateujdGjRyMxMbHAfahUKiiVSp2FiIiIyi5JA1BCQgLUajWcnJx01js5OSE2NvaV9jFlyhS4urrqhKhOnTph48aNCAsLw/z583H06FF07twZarU6330EBQVBoVBoFzc3t6IfFBEREek9M6kLeBPz5s3Dli1bEB4eDktLS+36vn37an9u2LAhPD098dZbbyE8PBzt27fPs5/AwEAEBARoXyuVSoYgIiKiMkzSHiAHBweYmpoiLi5OZ31cXBycnZ0Lfe/ChQsxb948HDx4EJ6enoW2rVGjBhwcHHDr1q18t8vlctjY2OgsREREVHZJGoAsLCzQpEkThIWFaddpNBqEhYXB19e3wPctWLAAc+bMQWhoKJo2bfrSz3n48CESExPh4uJSLHUTERGRYZP8NviAgACsXr0aGzZswNWrVzF69GikpaVh8ODBAIBPP/0UgYGB2vbz58/H9OnTsW7dOri7uyM2NhaxsbFITU0FAKSmpmLy5Mk4efIk7t27h7CwMPTo0QM1a9aEv7+/JMdIRERE+kXyMUB9+vTBkydPMGPGDMTGxsLb2xuhoaHagdHR0dEwMfk3p61YsQJZWVno1auXzn5mzpyJWbNmwdTUFBcvXsSGDRuQlJQEV1dXdOzYEXPmzIFcLi/VYyMiIiL9JPlzgPQRnwNERERkeAzmOUBEREREUmAAIiIiIqMj+RggMi6ZmYBMBnA4FhFR2SdE7u99pTJ3SU7+908PD6BBA+lqYwCiYqNSAQ8f5i4PHuQu//35wQMgMTE3ALm5ATVrAm+9lffP8uWlPhIiIsrOzhta8gsyL9uWnZ3//r/+mgGIDEBWFvD4sW6YeTHoxMe/2r6EAKKjc5fDh/Nud3LSDUX//fmFKd+IiOgFajWQmvp6ISW/bRkZxVeTTAZUqAAoFICNTe6frq7Ft/+iYAAiZGcDMTEFB5sHD4C4uNzg8jJWVrm9O1Wq5P6Z3885OcCtW7nL7du6fyYk5H5WXBxw4kTe/dva5g1Fz/90ds79S0ZEZIiEANLTCw4nrxpgUlKKt65y5XJDy/Pgkt+fhW1TKHL38Z8n2ugF3gafj7J0G7xa/W+4KejSVGwsoNG8fF9yeeHBxs0tt4fmTUJIcvK/YejFgPToUeHvtbbO/5JazZq5tZmaFr0uIqKCCAGkpf0bQF5lKSjAvMrv4lcll796SCloW4UKgJkBdZW8zvc3A1A+DCUAqdW5PSUvjrP57+uYmNx2L2Nu/m+IKSjkODhI28OSng7cuZO31+j2beDevcJ/cZibA9Wr539prXp1wMKi1A6DiPTE80tFhQWUV1lSUoo3uJiavn4vS37rjPFmk9f5/jagXGdcNBrgyZPCx9w8epR7OellzMyAypULDjZubkClSvrXPfkia+vcAXP5DZrLygLu38+/9+jOndztN27kLi8yMfl3UPaLvUdvvZXbdUtE+uP54Nw3Xf5vBqVi8zy4/Hf5b0D57/J8PEx+AcbampfzSwN7gPJR0j1AQuSOdSlszM2jR7lf2i9jYpI7kKygYFOlSu6gYmO+/KNW557P/MYc3bqV23VdGGfngscd2dmVzjGQ4dFocv8OZ2bm3iH5fMnMLPgfLvl96RX0RVgSbUvr/UW5ZPTfpTgH5wL/Xip608XKisFFarwE9oZKKgAFBwOLF+eGHJXq5e1lMsDFpfDLUs7OhnV9Vt8IkXv32ouh6PnPT58W/n57+7yh6PnPTk78ZVja1Or8A4cUrwu69ZeKj7V18QQXY7xUVFbxEpieUqlyv1ifc3Yu/LKUi0vu2BUqOTJZblBxcgJatcq7/dmz/HuNbt/OHV/19GnucuZM3veWK5f/rfxVq+b2yAlRcgtQsvt/0yU7u2QCyKuMd5OKXJ67WFrm/qMlv16RFxX0z9OSaFua7wd07yx6leXFS0mGNjiX9A97gPJRUj1A0dG5g3Xd3HLH5HDgrWFLS8sdX5TfHWvR0cU7KJJen0yWGzb+Gzye//zi68K2Fcd7zc3ZG0hUGtgDpKeqVs1dqGwoVw5o2DB3eZFKlRt28+s9evgw91/FMlnpLEDpfdarLubmJR9E8utlISJ6jgGIqATI5UDt2rkLERHpHz2/8ZmIiIio+DEAERERkdFhACIiIiKjwwBERERERocBiIiIiIwOAxAREREZHQYgIiIiMjoMQERERGR0GICIiIjI6DAAERERkdFhACIiIiKjwwBERERERocBiIiIiIwOAxAREREZHTOpC9BHQggAgFKplLgSIiIielXPv7eff48XhgEoHykpKQAANzc3iSshIiKi15WSkgKFQlFoG5l4lZhkZDQaDR4/fowKFSpAJpNJXQ6A3FTr5uaGBw8ewMbGRupyDAbPW9Hx3BUdz13R8LwVHc9dLiEEUlJS4OrqChOTwkf5sAcoHyYmJqhSpYrUZeTLxsbGqP/nLiqet6LjuSs6nrui4XkrOp47vLTn5zkOgiYiIiKjwwBERERERocByEDI5XLMnDkTcrlc6lIMCs9b0fHcFR3PXdHwvBUdz93r4yBoIiIiMjrsASIiIiKjwwBERERERocBiIiIiIwOAxAREREZHQagEnLs2DF069YNrq6ukMlk2Llzp852IQRmzJgBFxcXWFlZwc/PDzdv3tRp8/TpU/Tv3x82NjawtbXF0KFDkZqaqtPm4sWLaNOmDSwtLeHm5oYFCxbkqeXXX39FnTp1YGlpiYYNG2L//v3FfrzFKSgoCM2aNUOFChXg6OiInj174vr16zptMjMzMWbMGFSsWBHly5fHhx9+iLi4OJ020dHR6Nq1K6ytreHo6IjJkycjJydHp014eDgaN24MuVyOmjVrIiQkJE89wcHBcHd3h6WlJXx8fHD69OliP+bisGLFCnh6emofhObr64s//vhDu53n7NXMmzcPMpkM48eP167juSvYrFmzIJPJdJY6depot/PcFezRo0f45JNPULFiRVhZWaFhw4Y4e/asdju/J0qYoBKxf/9+8dVXX4nff/9dABA7duzQ2T5v3jyhUCjEzp07xYULF0T37t1F9erVRUZGhrZNp06dhJeXlzh58qT466+/RM2aNUW/fv2025OTk4WTk5Po37+/iIqKEps3bxZWVlbi559/1rY5ceKEMDU1FQsWLBBXrlwRX3/9tTA3NxeXLl0q8XNQVP7+/mL9+vUiKipKREZGii5duoiqVauK1NRUbZtRo0YJNzc3ERYWJs6ePStatGghWrZsqd2ek5MjGjRoIPz8/MT58+fF/v37hYODgwgMDNS2uXPnjrC2thYBAQHiypUr4scffxSmpqYiNDRU22bLli3CwsJCrFu3Tly+fFkMHz5c2Nrairi4uNI5Ga9h9+7dYt++feLGjRvi+vXrYtq0acLc3FxERUUJIXjOXsXp06eFu7u78PT0FF988YV2Pc9dwWbOnCnq168vYmJitMuTJ0+023nu8vf06VNRrVo1MWjQIHHq1Clx584dceDAAXHr1i1tG35PlCwGoFLwYgDSaDTC2dlZfP/999p1SUlJQi6Xi82bNwshhLhy5YoAIM6cOaNt88cffwiZTCYePXokhBDip59+EnZ2dkKlUmnbTJkyRdSuXVv7+qOPPhJdu3bVqcfHx0eMHDmyWI+xJMXHxwsA4ujRo0KI3HNlbm4ufv31V22bq1evCgAiIiJCCJEbQE1MTERsbKy2zYoVK4SNjY32fH355Zeifv36Op/Vp08f4e/vr33dvHlzMWbMGO1rtVotXF1dRVBQUPEfaAmws7MTa9as4Tl7BSkpKcLDw0McOnRIvPPOO9oAxHNXuJkzZwovL698t/HcFWzKlCmidevWBW7n90TJ4yUwCdy9exexsbHw8/PTrlMoFPDx8UFERAQAICIiAra2tmjatKm2jZ+fH0xMTHDq1Cltm7fffhsWFhbaNv7+/rh+/TqePXumbfPfz3ne5vnnGILk5GQAgL29PQDg3LlzyM7O1jmuOnXqoGrVqjrnr2HDhnByctK28ff3h1KpxOXLl7VtCjs3WVlZOHfunE4bExMT+Pn56f35U6vV2LJlC9LS0uDr68tz9grGjBmDrl275jk+nruXu3nzJlxdXVGjRg30798f0dHRAHjuCrN79240bdoUvXv3hqOjIxo1aoTVq1drt/N7ouQxAEkgNjYWAHT+wj9//XxbbGwsHB0ddbabmZnB3t5ep01++/jvZxTU5vl2fafRaDB+/Hi0atUKDRo0AJB7TBYWFrC1tdVp++L5K+q5USqVyMjIQEJCAtRqtUGdv0uXLqF8+fKQy+UYNWoUduzYgXr16vGcvcSWLVvwzz//ICgoKM82nrvC+fj4ICQkBKGhoVixYgXu3r2LNm3aICUlheeuEHfu3MGKFSvg4eGBAwcOYPTo0fj888+xYcMGAPyeKA2cDZ702pgxYxAVFYXjx49LXYpBqF27NiIjI5GcnIzffvsNAwcOxNGjR6UuS689ePAAX3zxBQ4dOgRLS0upyzE4nTt31v7s6ekJHx8fVKtWDdu2bYOVlZWElek3jUaDpk2bYu7cuQCARo0aISoqCitXrsTAgQMlrs44sAdIAs7OzgCQ506IuLg47TZnZ2fEx8frbM/JycHTp0912uS3j/9+RkFtnm/XZ2PHjsXevXtx5MgRVKlSRbve2dkZWVlZSEpK0mn/4vkr6rmxsbGBlZUVHBwcYGpqalDnz8LCAjVr1kSTJk0QFBQELy8vLF26lOesEOfOnUN8fDwaN24MMzMzmJmZ4ejRo1i2bBnMzMzg5OTEc/cabG1tUatWLdy6dYv/3xXCxcUF9erV01lXt25d7eVDfk+UPAYgCVSvXh3Ozs4ICwvTrlMqlTh16hR8fX0BAL6+vkhKSsK5c+e0bQ4fPgyNRgMfHx9tm2PHjiE7O1vb5tChQ6hduzbs7Oy0bf77Oc/bPP8cfSSEwNixY7Fjxw4cPnwY1atX19nepEkTmJub6xzX9evXER0drXP+Ll26pPPL4dChQ7CxsdH+0nnZubGwsECTJk102mg0GoSFhen1+fsvjUYDlUrFc1aI9u3b49KlS4iMjNQuTZs2Rf/+/bU/89y9utTUVNy+fRsuLi78/64QrVq1yvN4jxs3bqBatWoA+D1RKqQehV1WpaSkiPPnz4vz588LAOKHH34Q58+fF/fv3xdC5N7eaGtrK3bt2iUuXrwoevToke/tjY0aNRKnTp0Sx48fFx4eHjq3NyYlJQknJycxYMAAERUVJbZs2SKsra3z3N5oZmYmFi5cKK5evSpmzpyp97c3jh49WigUChEeHq5za216erq2zahRo0TVqlXF4cOHxdmzZ4Wvr6/w9fXVbn9+a23Hjh1FZGSkCA0NFZUqVcr31trJkyeLq1eviuDg4HxvrZXL5SIkJERcuXJFjBgxQtja2urcsaIvpk6dKo4ePSru3r0rLl68KKZOnSpkMpk4ePCgEILn7HX89y4wIXjuCjNx4kQRHh4u7t69K06cOCH8/PyEg4ODiI+PF0Lw3BXk9OnTwszMTHz33Xfi5s2b4n//+5+wtrYWv/zyi7YNvydKFgNQCTly5IgAkGcZOHCgECL3Fsfp06cLJycnIZfLRfv27cX169d19pGYmCj69esnypcvL2xsbMTgwYNFSkqKTpsLFy6I1q1bC7lcLipXrizmzZuXp5Zt27aJWrVqCQsLC1G/fn2xb9++Ejvu4pDfeQMg1q9fr22TkZEhPvvsM2FnZyesra3F+++/L2JiYnT2c+/ePdG5c2dhZWUlHBwcxMSJE0V2drZOmyNHjghvb29hYWEhatSoofMZz/3444+iatWqwsLCQjRv3lycPHmyJA77jQ0ZMkRUq1ZNWFhYiEqVKon27dtrw48QPGev48UAxHNXsD59+ggXFxdhYWEhKleuLPr06aPzLBueu4Lt2bNHNGjQQMjlclGnTh2xatUqne38nihZMiGEkKbviYiIiEgaHANERERERocBiIiIiIwOAxAREREZHQYgIiIiMjoMQERERGR0GICIiIjI6DAAERERkdFhACIiIiKjwwBERERERocBiIiIiIyOmdQFEBGVhrZt28LT0xOWlpZYs2YNLCwsMGrUKMyaNUvq0ohIAuwBIiKjsWHDBpQrVw6nTp3CggUL8M033+DQoUNSl0VEEuBkqERkFNq2bQu1Wo2//vpLu6558+Z49913MW/ePAkrIyIpsAeIiIyGp6enzmsXFxfEx8dLVA0RSYkBiIiMhrm5uc5rmUwGjUYjUTVEJCUGICIiIjI6DEBERERkdBiAiIiIyOjwLjAiIiIyOuwBIiIiIqPDAERERERGhwGIiIiIjA4DEBERERkdBiAiIiIyOgxAREREZHQYgIiIiMjoMAARERGR0WEAIiIiIqPDAERERERGhwGIiIiIjA4DEBERERmd/w+DoD5gA0ngCwAAAABJRU5ErkJggg==",
      "text/plain": [
       "<Figure size 640x480 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "backward:\n",
      "         n    Triton     Torch\n",
      "0   8192.0  0.154183  0.453055\n",
      "1  16384.0  0.192495  0.516526\n",
      "2  24576.0  0.144959  0.797048\n",
      "3  32768.0  0.146263  1.048884\n",
      "4  40960.0  0.155951  1.273290\n",
      "5  49152.0  0.155707  1.494620\n",
      "6  57344.0  0.174456  1.711335\n",
      "7  65536.0  0.193731  1.927839\n"
     ]
    }
   ],
   "source": [
    "torch.cuda.empty_cache()\n",
    "@triton.testing.perf_report(\n",
    "    triton.testing.Benchmark(\n",
    "        x_names=['n'],  # argument names to use as an x-axis for the plot\n",
    "        x_vals=[8192 * i for i in range(1, 8+1)],  # different possible values for `x_name`\n",
    "        line_arg='provider',  # argument name whose value corresponds to a different line in the plot\n",
    "        line_vals=['triton', 'torch'],  # possible values for `line_arg``\n",
    "        line_names=[\n",
    "            \"Triton\",\n",
    "            \"Torch\",\n",
    "        ],  # label name for the lines\n",
    "        styles=[('blue', '-'), ('green', '-')],  # line styles\n",
    "        ylabel=\"ms\",  # label name for the y-axis\n",
    "        plot_name=\"backward\",  # name for the plot. Used also as a file name for saving the plot.\n",
    "        args={'b':1, 'h':4, 'd':128, 'stride':16, 'kernel_size':32},  # values for function arguments not in `x_names` and `y_name`\n",
    "    ))\n",
    "def benchmark(b, provider, h, n, d, stride, kernel_size):\n",
    "    device = 'cuda'\n",
    "    dtype = torch.bfloat16\n",
    "    x = torch.randn(b, n, h, d, device=device, dtype=dtype)\n",
    "    x.requires_grad_(True)\n",
    "    weight = torch.nn.Parameter(torch.randn(kernel_size, device=device, dtype=dtype))\n",
    "    pe = torch.nn.Parameter(torch.randn(kernel_size, d, device=device, dtype=dtype))\n",
    "\n",
    "    stream = torch.cuda.Stream()\n",
    "    torch.cuda.set_stream(stream)\n",
    "    if provider == 'torch':\n",
    "        y = torch_blcok_compress(x, weight, pe, stride)\n",
    "        dy = torch.randn_like(y)\n",
    "        ms = triton.testing.do_bench(lambda: y.backward(dy, retain_graph=True), grad_to_none=[x, weight, pe])\n",
    "    if provider == 'triton':\n",
    "        y = triton_block_compress(x, weight, pe, stride)\n",
    "        dy = torch.randn_like(y)\n",
    "        ms = triton.testing.do_bench(lambda: y.backward(dy, retain_graph=True), grad_to_none=[x, weight, pe])\n",
    "    return ms\n",
    "benchmark.run(show_plots=True, print_data=True)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## attention\n",
    "- 对比三种实现方式"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 精度"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "n = 8192 \n",
    "kernel_size = 32\n",
    "stride = 16\n",
    "select_size = 64\n",
    "# flex_attn必须要head_dim是2的指数倍\n",
    "b, qh, kh, d, vd = 1, 64, 4, 128, 128\n",
    "device = 'cuda'\n",
    "dtype = torch.float16\n",
    "num_blocks = (n - kernel_size) // stride + 1\n",
    "q1 = torch.randn(b, n, qh, d, device=device, dtype=dtype)\n",
    "ck1 = torch.randn(b, num_blocks, kh, d, device=device, dtype=dtype)\n",
    "cv1 = torch.randn(b, num_blocks, kh, vd, device=device, dtype=dtype)\n",
    "q1.requires_grad_(True)\n",
    "ck1.requires_grad_(True)\n",
    "cv1.requires_grad_(True)\n",
    "q2 = deepcopy(q1)\n",
    "ck2 = deepcopy(ck1)\n",
    "cv2 = deepcopy(cv1)\n",
    "q3 = deepcopy(q1)\n",
    "ck3 = deepcopy(ck1)\n",
    "cv3 = deepcopy(cv1)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "========== triton vs torch\n",
      "0.00244140625 \t 5.745887756347656e-05\n",
      "0.00390625 \t 5.728006362915039e-05\n",
      "0.0234375 \t 0.0009217262268066406\n",
      "0.03125 \t 0.0009174346923828125\n",
      "========== triton vs flex\n",
      "0.001953125 \t 4.494190216064453e-05\n",
      "0.00390625 \t 5.418062210083008e-05\n",
      "0.029296875 \t 0.0008544921875\n",
      "0.03125 \t 0.0007448196411132812\n"
     ]
    }
   ],
   "source": [
    "y1 = torch_cmp_attn(q1, ck1, cv1, kernel_size, stride)\n",
    "\n",
    "y3, lse3 = triton_compress_attn_v1(q3, ck3, cv3, kernel_size, stride)\n",
    "\n",
    "# dy12不是连续的，dy3要求是连续的\n",
    "dy12 = torch.randn_like(y1)\n",
    "dy3 = torch.rand_like(y3)\n",
    "dy3.data.copy_(dy12)\n",
    "\n",
    "y1.backward(dy12)\n",
    "\n",
    "y3.backward(dy3)\n",
    "\n",
    "print('='*10 + ' triton vs torch')\n",
    "print((y1-y3).abs().max().item(), '\\t',(y1-y3).abs().mean().item())\n",
    "print((q1.grad-q3.grad).abs().max().item(), '\\t',(q1.grad-q3.grad).abs().mean().item())\n",
    "print((ck1.grad-ck3.grad).abs().max().item(),'\\t', (ck1.grad-ck3.grad).abs().mean().item())\n",
    "print((cv1.grad-cv3.grad).abs().max().item(),'\\t', (cv1.grad-cv3.grad).abs().mean().item())\n",
    "# 由于是GQA，kv梯度进行bf16的累加，如果是fp32或者fp16会减少误差\n",
    "if math.log2(d).is_integer():\n",
    "    y2 = flex_cmp_attn(q2, ck2, cv2, kernel_size, stride)\n",
    "    y2.backward(dy12)\n",
    "    print('='*10 + ' triton vs flex')\n",
    "    print((y2-y3).abs().max().item(), '\\t',(y2-y3).abs().mean().item())\n",
    "    print((q2.grad-q3.grad).abs().max().item(), '\\t',(q2.grad-q3.grad).abs().mean().item())\n",
    "    print((ck2.grad-ck3.grad).abs().max().item(), '\\t',(ck2.grad-ck3.grad).abs().mean().item()) \n",
    "    print((cv2.grad-cv3.grad).abs().max().item(), '\\t',(cv2.grad-cv3.grad).abs().mean().item())"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### foward"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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",
      "text/plain": [
       "<Figure size 640x480 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "forward:\n",
      "         n  triton-v1  Torch  Flex  triton-v2\n",
      "0   8192.0   0.360411   10.0  10.0   0.355078\n",
      "1  16384.0   1.211104   10.0  10.0   1.203133\n",
      "2  24576.0   2.552417   10.0  10.0   2.566982\n",
      "3  32768.0   4.402770   10.0  10.0   4.436821\n",
      "4  40960.0   6.739471   10.0  10.0   6.822478\n",
      "5  49152.0   9.593306   10.0  10.0   9.728149\n",
      "6  57344.0  12.949540   10.0  10.0  13.147432\n",
      "7  65536.0  16.799526   10.0  10.0  17.067423\n"
     ]
    }
   ],
   "source": [
    "torch.cuda.empty_cache()\n",
    "@triton.testing.perf_report(\n",
    "    triton.testing.Benchmark(\n",
    "        x_names=['n'],  # argument names to use as an x-axis for the plot\n",
    "        x_vals=[8192 * i for i in range(1, 8+1)],  # different possible values for `x_name`\n",
    "        line_arg='provider',  # argument name whose value corresponds to a different line in the plot\n",
    "        line_vals=['triton-v1', 'torch', 'flex', 'triton-v2'],  # possible values for `line_arg``\n",
    "        line_names=[\n",
    "            \"triton-v1\",\n",
    "            \"Torch\",\n",
    "            \"Flex\",\n",
    "            \"triton-v2\",\n",
    "        ],  # label name for the lines\n",
    "        styles=[('blue', '-'), ('green', '-'), ('red', '-'), ('orange', '-')],  # line styles\n",
    "        ylabel=\"ms\",  # label name for the y-axis\n",
    "        plot_name=\"forward\",  # name for the plot. Used also as a file name for saving the plot.\n",
    "        args={'b':1, 'qh':64, 'kh':4, 'd':128, 'vd':128, 'stride':16, 'kernel_size':32},  # values for function arguments not in `x_names` and `y_name`\n",
    "    ))\n",
    "def benchmark(b, qh, kh, n, d, vd, stride, kernel_size, provider):\n",
    "    device = 'cuda'\n",
    "    dtype = torch.bfloat16\n",
    "    num_blocks = (n - kernel_size) // stride + 1\n",
    "    q = torch.randn(b, n, qh, d, device=device, dtype=dtype)\n",
    "    ck = torch.randn(b, num_blocks, kh, d, device=device, dtype=dtype)\n",
    "    cv = torch.randn(b, num_blocks, kh, vd, device=device, dtype=dtype)\n",
    "    stream = torch.cuda.Stream()\n",
    "    torch.cuda.set_stream(stream)\n",
    "    if provider == 'torch':\n",
    "        if n > 4096:\n",
    "            return 10\n",
    "        ms = triton.testing.do_bench(lambda: torch_cmp_attn(q, ck, cv, kernel_size, stride))\n",
    "    if provider == 'triton-v1':\n",
    "        ms = triton.testing.do_bench(lambda: triton_compress_attn_v1(q, ck, cv, kernel_size, stride))\n",
    "    if provider == 'flex':\n",
    "        if n > 4096:\n",
    "            return 10\n",
    "        if not math.log2(d).is_integer():\n",
    "            return 10\n",
    "        ms = triton.testing.do_bench(lambda: flex_cmp_attn(q, ck, cv, kernel_size, stride))\n",
    "    if provider == 'triton-v2':\n",
    "        ms = triton.testing.do_bench(lambda: triton_compress_attn_v2(q, ck, cv, kernel_size, stride))\n",
    "    return ms\n",
    "benchmark.run(show_plots=True, print_data=True)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### backward"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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40J5dMQ8qtf0YOrU/HmF0s04SEy5zmKx/ONryJAhZkcUERFHYBiwtQ/ERJKU7kPLYQtx8Qlk/nzw8jI7XNbpZF8Hc+7cOfufZ82axQcffMDBgwft03xu8/q49PR0XF1dcyyfiIg4iINj4cgkbIaFTl9O58iFmqxdC6VKmR3s9mhExsEEBQXZX35+flgsFvv7kiVL8sUXX1C6dGnc3d2pXbs2y5Yts3/2xIkTWCwWZs2axYMPPoiHhwfTpk0D4Pvvv6datWq4u7sTHBzMq6++mul7L1y4wJNPPomXlxcVKlRgwYIFefpzi4hIDjq7FLb3B+CN6Z+zaPtjTJ0K9eubnCsbNCJzA8MwSEpPMuW7vVy9sFgsd7SOL7/8klGjRjFp0iTq1KnD999/z+OPP87evXupUKGCfbm3336bUaNGUadOHTw8PJg4cSL9+/dn+PDhtGrViri4ONavX59p3R9++CEjRozg888/56uvvqJLly6cPHmSgICAO8osIiJ57MpeWNcJDBvfr+nOF0v689FH0KGD2cGyR0XmBknpSfgMM+fWhQmDEvB2876jdYwcOZK33nqLp59+GoDPPvuMVatWMWbMGMaPH29frm/fvjz11FP295988gkDBgzg9ddft0+75557Mq27W7dudO7cGYChQ4cyduxYNm/eTMuWLe8os4iI5KGU89eeoZRxlXWHH6TXdxPo3NnCe++ZHSz7dGipgIiPj+fs2bM0btw40/TGjRuzf//+TNPq3zB2GBsby9mzZ2natOk/rr9mzZr2P3t7e+Pr60tsbGwOJBcRkTxhTb32NOvE45y8dDdPjPyVuvXd+O47uMMDAqbSiMwNvFy9SBiUYNp35xVv7/8f+fH09MzSZ/56QrDFYsFms+VoLhERySWGAZt7wvn1JKT60WLoIryLFmPePMjibiDfUpG5gcViuePDO2bx9fUlJCSE9evX8+CDD9qnr1+/ngYNGtzyc0WKFKFcuXJERETw0EMP5UVUERHJa/s+g+M/YDWcefKL2ZyOr8z69RAUZHawO6ciU4C88cYbDB48mLvvvpvatWszefJkduzYYb8y6VaGDBlCr169KFmyJK1ateLq1ausX7+ePn365FFyERHJNafmws5BALw29Usi9jZnzhyoVcvkXDlERaYAee2114iLi2PAgAHExsZStWpVFixYkOmKpZvp2rUrKSkpjB49moEDB1K8eHHat2+fR6lFRCTXXNoOfzwLwPiVvZmwsjfDh0PbtubGykkWwzAMs0Pkpvj4ePz8/IiLi8PX1zfTvJSUFI4fP05YWBgeHh4mJZTbod+ZiEgWJZ+D5Q0g6TQR+x6hxbDFPPucC5MnO8bJvf+0/76RrloSEREpaDKSYc0TkHSaI+cr0270LO4Nd2HSJMcoMbdDRUZERKQgMWywsRtc2kJcSgAthi6iaEl/5s4Fd3ezw+U8nSMjIiJSkOz+CKJ+JsPmyuOfz+F88t38EQElSpgdLHeoyIiIiBQUJ2bCng8B6Pnt16w79CALF0L16ibnykUqMiIiIgXBhU3XDikBIxcPZPKaF/niC2jd2txYuU3nyIiIiDi6xChY+wTYUlm883HemjGcHj2gb1+zg+U+FRkRERFHlp4Aax6HlBj2n6vJ02N/4oEHnRk3ruBdoXQzKjIiIiKOyrDBH13gyk4uJZWk5fAFBJUuwi+/gJub2eHyhs6RERERcVQ7BsGZBaRZ3Wn92Xzi0suycSEUK2Z2sLyjEZkCqEmTJvQtDAdGRUQKs2NTYP8IALp9/T1bj9/L7NlQubK5sfKaioyD6tatGxaL5W+vI0eOmB1NRERyW+xa2NwTgI/nvs+MP57hyy+heXOTc5lAh5YcWMuWLZk8eXKmaSUK6h2PRETkmqtH4fenwJbOnK3tGfzrEHr3ht69zQ5mDo3IODB3d3eCgoIyvZydnf+2XGpqKgMHDqRUqVJ4e3vTsGFDVq9eDVx7CGO1atXo2bOnffmjR49SpEgRvv/++7z6UUREJCvS4mDNY5B6kZ2n6vPs+Kk0berEmDFmBzOPRmRuZBiQlGTOd3t55dp1cq+++ir79u1j5syZhISEMHfuXFq2bMnu3bupUKEC06ZNo2HDhrRp04ZHH32UZ599lubNm/Piiy/mSh4REckGWwas7wTx+4lNKEWr4fMJDfNi9mxwKcR780L8o99EUhL4+Jjz3QkJ4O19Wx9ZtGgRPjfkbdWqFbNnz860TFRUFJMnTyYqKoqQkBAABg4cyLJly5g8eTJDhw6ldu3afPLJJ7z00ks8/fTTnDx5kkWLFt35zyQiIjnnz/5wbjkpGV60HLaAFEsIaxeBv7/ZwcylIuPAHnroISZOnGh/732TIrR7926sVisVK1bMND01NZViN1yfN2DAAObNm8e4ceNYunRppnkiImKywxPh0FcAPPPVj+w+XZcVK6B8eZNz5QMqMjfy8ro2MmLWd98mb29vyv/L3+KEhAScnZ3Ztm3b386fuXE0JzY2lkOHDuHs7Mzhw4dp2bLlbecREZFccG4lbO0DwDuzPmXu1qf45ht46CGTc+UTKjI3slhu+/BOflenTh2sViuxsbHcf//9t1zuxRdfpEaNGnTv3p0ePXrQrFkzqlSpkodJRUTkb+IOwLoOYFiZ9sdzDFswiH79oEcPs4PlHyoyBVzFihXp0qULzz//PKNGjaJOnTqcP3+eiIgIatasSZs2bRg/fjwbNmxg165dlClThsWLF9OlSxc2btyIW2G5x7WISH6TevHaFUrpcWw53ogXJ/2X1q0tfP652cHyF11+XQhMnjyZ559/ngEDBlCpUiXatm3Lli1bCA0N5cCBA7zxxhtMmDCBMmXKADBhwgQuXLjA+++/b3JyEZFCypoGv7eHhCOciStHmxFzqVDJnRkz4CZ32SjULIZhGGaHyE3x8fH4+fkRFxeHr69vpnkpKSkcP36csLAwPDw8TEoot0O/MxEp8Azj2l17j35LcroP97y3gZiU6mzeDGFhZofLO/+0/76RDi2JiIjkJwdGw9FvsRlOtB8zk0Mx1YmMLFwl5naoyIiIiOQXZxbB9oEADPhpJEt2tGHKFLjvPnNj5Wc6R0ZERCQ/uLIb1ncGDL5b04Mxy/ry1lvQtavZwfI3FRkRERGzpcReu0IpI4H1R5rQ67vxPPGEhaFDzQ6W/5laZIYMGYLFYsn0qly5sn1+SkoKvXv3plixYvj4+NCuXTtiYmJMTCwiIpLDrCmwti0knuTkpfI8NuJXqlV35aefwEnDDf/K9E1UrVo1zp07Z3+tW7fOPq9fv34sXLiQ2bNns2bNGs6ePctTTz1lYloREZEcZBiw6SW4sIGENH8eGboIN58AFiww79F/jsb0k31dXFwICgr62/S4uDi+++47pk+fzsMPPwxcux9KlSpV2LhxI/fee29eRxUREclZ+4bBiWlYDWfajpzNyUuVWL0aQkPNDuY4TB+ROXz4MCEhIdx111106dKFqKgoALZt20Z6ejrNmjWzL1u5cmVCQ0PZsGHDLdeXmppKfHx8ppeIiEi+E/Ur7HwXgN6TxxGxtxmTJ4P+P/32mFpkGjZsyJQpU1i2bBkTJ07k+PHj3H///Vy9epXo6Gjc3Nzw/8vzyQMDA4mOjr7lOocNG4afn5/9df1utSIiIvnGpW2w4TkAvlrxGpMievH++9C5s8m5HJCpRaZVq1Z06NCBmjVr0qJFC5YsWcKVK1f4+eefs73OQYMGERcXZ3+dOnUqBxM7niFDhlC7dm2zY4iIyHVJZ2DN42BNJnJ/C/r9OIr27WHIELODOSbTDy3dyN/fn4oVK3LkyBGCgoJIS0vjypUrmZaJiYm56Tk117m7u+Pr65vpVRA1adKEvn37/utyAwcOJCIiwv6+W7dutG3bNveC3YYTJ07QvXt3wsLC8PT05O6772bw4MGkpaWZHU1EJHdkJMHaJyD5LEfOV+XJUbOoXceFqVN1hVJ25avNlpCQwNGjRwkODqZevXq4urpm2gkfPHiQqKgowsPDTUzpGAzDICMjAx8fH4oVK2Z2nJs6cOAANpuNSZMmsXfvXkaPHs3XX3/NO++8Y3Y0EZGcZ9hgQ1e4tI24lOI88ulCfIr6MX8+eHmZHc6BGSYaMGCAsXr1auP48ePG+vXrjWbNmhnFixc3YmNjDcMwjF69ehmhoaFGZGSksXXrViM8PNwIDw+/re+Ii4szACMuLu5v85KTk419+/YZycnJOfLz5JWuXbsaQKbX5MmTDcBYsmSJUbduXcPV1dVYtWqVMXjwYKNWrVqGYRjG4MGD//a5VatWGYZhGLt27TIeeughw8PDwwgICDB69OhhXL16NdN3PvHEE8bnn39uBAUFGQEBAcYrr7xipKWl3TRjXFyc4eHhYSxZsiTT9Dlz5hg+Pj5GYmLiTT83YsQIIyws7JY/u6P+zkREjB3vGcY0jPQfXY37Kq01PD0NY+tWs0PlX/+0/76RqZdfnz59ms6dO3Px4kVKlCjBfffdx8aNGylRogQAo0ePxsnJiXbt2pGamkqLFi2YMGFC7gUyDLAm5d76/4mzF1gsWVr0yy+/5NChQ1SvXp2PPvoIgL179wLw9ttvM3LkSO666y6KFi3K6tWr7Z8bOHAg+/fvJz4+nsmTJwMQEBBAYmIiLVq0IDw8nC1bthAbG8tLL73Eq6++ypQpU+yfX7VqFcHBwaxatYojR47QqVMnateuTY8ePf6W0dfXl0cffZTp06fTqlUr+/Rp06bRtm1bvG7xvx9xcXEEBARkaTuIiDiM49Ng7ycAvPTfb1h38H5mz4Z69UzOVQCYWmRmzpz5j/M9PDwYP34848ePz5tA1iT42aQ7EHVMABfvLC3q5+eHm5sbXl5e9vOFDhw4AMBHH31E8+bNb/o5Hx8fPD09SU1NzXSe0dSpU0lJSeGHH37A2/tahnHjxvHYY4/x2WefERgYCEDRokUZN24czs7OVK5cmTZt2hAREXHTIgPQpUsXnnvuOZKSkvDy8iI+Pp7Fixczd+7cmy5/5MgRvvrqK0aOHJml7SAi4hDOb4BN3QH4fPGbTF3bjY8/hvbtTc5VQOSrc2TkztWvX/+2P7N//35q1aplLzEAjRs3xmazcfDgQfu0atWq4ezsbH8fHBxMbGwsAEOHDsXHx8f+ioqKonXr1ri6urJgwQIAfv31V3x9fTPdG+i6M2fO0LJlSzp06HDLYiQi4nAST8LvbcGWyuKdT/DWjGE88wy8+67ZwQoO0+/sm684e10bGTHru3PAjWUkp7m6umZ6b7FYsNlsAPTq1YuOHTva54WEhODi4kL79u2ZPn06Tz/9NNOnT6dTp064uGT+a3f27FkeeughGjVqxDfffJNr+UVE8lT61WsPgkyJZX90LTp9+RMNGjjx3XdZPpNAskBF5kYWS5YP75jNzc0Nq9WaI5+rUqUKU6ZMITEx0V6E1q9fj5OTE5UqVcrSegMCAm56bkuXLl1o3rw5e/fuJTIykk8++STT/DNnzvDQQw9Rr149Jk+ejJOuPxSRgsBmhfXPwJXdXEwK4pFPFxJQ0od588DDw+xwBYv2Gg6qXLlybNq0iRMnTnDhwgX7yEhWPrdr1y4OHjzIhQsXSE9Pp0uXLnh4eNC1a1f27NnDqlWr6NOnD88995z9/JjseuCBBwgKCqJLly6EhYXRsGFD+7wzZ87QpEkTQkNDGTlyJOfPnyc6Ovof79wsIuIQdrwFZxeRZvWg1bD5XE4tw8KF8A+3QZNsUpFxUAMHDsTZ2ZmqVatSokQJ+zOq/k2PHj2oVKkS9evXp0SJEqxfvx4vLy+WL1/OpUuXuOeee2jfvj1NmzZl3Lhxd5zTYrHQuXNndu7cSZcuXTLNW7lyJUeOHCEiIoLSpUsTHBxsf4mIOKyj38GBUQA8P2EyW483YPp0qFXL5FwFlMUwDMPsELkpPj4ePz8/4uLi/naX35SUFI4fP05YWBgeGutzCPqdiUi+FrMaIpuDkcFHcwcz+JchfPYZvPmm2cEczz/tv2+kERkREZGccPUI/N4OjAx+3dqJwb8MpmtXeOMNs4MVbCoyIiIidyrtyrUrlNIusfP0PTw7bjL33Wdh0iRdoZTbVGRERETuhC0D1nWE+APEJpSm5bD5BJXyZM4ccHc3O1zBp8uvRURE7sS21yF6JalWL1oMXUCiNZjfFsH/nrYjuUxFhmtPihbHoN+ViOQrh8bD4QkYhoVOX05j16k6LFoE1aqZHazwKNSHlq7fqTYpyaQHRcptS0tLA8j0qAQREVNE/QLbXgNg0KxhzN/WllGj4Ibn5EoeKNQjMs7Ozvj7+9ufF+Tl5YVFZ2XlWzabjfPnz+Pl5fW3xxyIiOSpM0tgfWcwbExZ9xKfLXyTHj3g9dfNDlb4FPq9wfWnQF8vM5K/OTk5ERoaqsIpIuaJWQ3rrl1mvWDn03T/+muaNLEwfryuUDJDoS8yFouF4OBgSpYsSXp6utlx5F+4ubnpeUwiYp4Lm65dZm1NIeLgY7Qb9QN3l3fml1/gL8/VlTxS6IvMdc7OzjrvQkREbu3yTljVEjIS2HC8KW2G/Uyp0q789hsUK2Z2uMJL/2srIiLyb+IOXHv0QPoVtp9uRPOP51Ei0IPISAgNNTtc4aYiIyIi8k8SjkNkM0g9z4GYOjz04WKKFPUhIgLuusvscKIiIyIicitJZ6+VmOQzHL9UhfsHL8fN25+ICKhY0exwAjpHRkRE5OZSzl8rMQnHOBN3F43f/w2bawlW/QZVq5odTq5TkREREfmrtCuwqgXE7yc2oTSNP4ggyQghYgXUrGl2OLmRioyIiMiN0hNgdWu4vJ3LySW5f8hvXEwpx8qVUK+e2eHkr1RkRERErrOmwNon4MIGEtL8afLRCk7HVWLZMrj3XrPDyc2oyIiIiADY0mFdR4iJJDndh6afLONQbC0WL4b77zc7nNyKioyIiIjNCn88B2cWkmb1oNVnC9lxqiHz58PDD5sdTv6JioyIiBRuhg0294SoWWTYXGk76lfWH27CnDnQsqXZ4eTfqMiIiEjhZRiwrR8c+x6b4USnsTNYsac1s2bBY4+ZHU6yQkVGREQKr13vw6GxALww6Xvmbm3HTz9Bu3Ym55IsU5EREZHCad9nsPdTAF6ZPJ4ffu/K5MnwzDMm55LbokcUiIhI4XNoPOx4G4A3Z3zGxN9eYdIk6NbN3Fhy+1RkRESkcDk2Bba+CsDHc9/j80VvMnYs9OxpbizJHhUZEREpPKJmw6buAIxZ+jof/PIRn38OffqYnEuyTUVGREQKhzNLYP0zYNj4dlV3+v00mo8/tjBwoNnB5E6oyIiISMEXsxrWtQMjgxl/PM1/vpvEe+9ZeO89s4PJnVKRERGRgu3CRljzKFhTmL/tcZ7/+gf6D3Dmo4/MDiY5QUVGREQKrss7YFUryEjktz1N6fTVLF5+xZURI8BiMTuc5AQVGRERKZjiDkDkI5B+hT8ONeKJL+bT9QUPvvxSJaYgUZEREZGCJ+E4RDaD1PNsP1GH1p8vpmNnbyZOVIkpaFRkRESkYEk6c63EJJ9h35mqNB+2gtZP+PPtt+CkvV6Bo1+piIgUHCnnr5WYhGMcjbmbZkNX0qRFcX74AZydzQ4nuUFFRkRECoa0K7DqEYg/wOlLpWk69Dfq3x/C9OngoicLFlgqMiIi4vjSE2B1a7i8g9j4kjQd+huV65Vj9mxwczM7nOQmFRkREXFs1hRY+wRc2MDlxKI0G7qSUpUrMXcuuLubHU5ym4qMiIg4Lls6/N4BYiJJSPGhxfBl+JWtycKF4OlpdjjJCyoyIiLimGxW+OM5OLuI5DQP2ny+CKcSDVi8GLy9zQ4neUWnP4mIiOMxbLC5J0TNIi3DlafGzCHB60EiloGvr9nhJC+pyIiIiGMxDNjWD459j9XmROdxMzhrtCJyBfj7mx1O8lq+ObQ0fPhwLBYLffv2tU9LSUmhd+/eFCtWDB8fH9q1a0dMTIx5IUVExHy73odDYwF4YdJk9ie0Y+VKKFbM5FxiinxRZLZs2cKkSZOoWbNmpun9+vVj4cKFzJ49mzVr1nD27Fmeeuopk1KKiIjp9g6HvZ8C8Mrk8WyMeZ6ICChZ0uRcYhrTi0xCQgJdunThv//9L0WLFrVPj4uL47vvvuOLL77g4Ycfpl69ekyePJk//viDjRs33nJ9qampxMfHZ3qJiEgBcHAc7BwEwJszPmPZ0VeIjITgYJNzialMLzK9e/emTZs2NGvWLNP0bdu2kZ6enml65cqVCQ0NZcOGDbdc37Bhw/Dz87O/ypQpk2vZRUQkjxybAtv6APDx3PeYufNNIiOhdGlzY4n5TC0yM2fO5M8//2TYsGF/mxcdHY2bmxv+fzlzKzAwkOjo6Fuuc9CgQcTFxdlfp06dyunYIiKSl6JmY2zsDsDopX2ZuP4jIiOhXDlzY0n+YNpVS6dOneL1119n5cqVeHh45Nh63d3dcdetHEVECoYzizHWP4MFG/9d9RLDV3zBmjUWypc3O5jkF6aNyGzbto3Y2Fjq1q2Li4sLLi4urFmzhrFjx+Li4kJgYCBpaWlcuXIl0+diYmIICgoyJ7SIiOSdmFUYv7fDYmQw/Y/OvDvvayIiLFSubHYwyU9MG5Fp2rQpu3fvzjTthRdeoHLlyrz11luUKVMGV1dXIiIiaNeuHQAHDx4kKiqK8PBwMyKLiEheubARY/VjWGypzN/2OK/PmMqK35ypXt3sYJLfmFZkihQpQvW//I309vamWLFi9undu3enf//+BAQE4OvrS58+fQgPD+fee+81I7KIiOSFyzswVrXCYk1k5e5mvDR5FouXuVKnjtnBJD/K13f2HT16NE5OTrRr147U1FRatGjBhAkTzI4lIiK5Je4ARuQjWNKvsO5gY7pMmse8hR40aGB2MMmvLIZhGGaHyE3x8fH4+fkRFxeHrx7AISKSfyUcx1h5P5bkM2w7Xpc2X0Qy81c/mjQxO5iYIav7b9PvIyMiIkLSGYyIpliSz7D3dFUeH72cH2eqxMi/U5ERERFzpZzHiGyGJfE4R6LvpvXIlXwztTjNm5sdTByBioyIiJgn7cq1c2LiD3DqYmke+SyCMZNCaNPG7GDiKFRkRETEHOkJGKtbY7myg5i4kjQfHsGwsWV58kmzg4kjUZEREZG8Z03BWPsElgsbuJRQlEeGr+Td4RXp1MnsYOJoVGRERCRv2dIxfu+AJSaSq8k+tPxsGX3er8lzz5kdTByRioyIiOQdmxX+eA7L2UUkp3nw6MhFdO3fgJdeMjuYOCoVGRERyRuGDTb3hKhZpGW48uToubTt+SC9e5sdTByZioyIiOQ+w4Bt/eDY91htTnQeN4MHn25Jv35mBxNHpyIjIiK5b9d7cGgsAC9MmkyN1u0YNMjkTFIgqMiIiEju2jsc9g4F4OXvJxDS+HkGDzY5kxQYKjIiIpJ7Do6DndeGXt6YPgKPGi8zbBhYLCbnkgIjXz/9WkREHNixKbCtDwAfzXmfxNA3GP+FSozkLBUZERHJeVGzMTZ2xwKMXtqXKP8P+WacSozkPBUZERHJWWcWY1v3DE7Y+O+ql/iTL5gyyYKTTmaQXKAiIyIiOSdmFdY17XAmg2nrn+G3uK+ZNt2Cs7PZwaSgUpEREZGccWEj1sjHcCaVeVufYM7ZKcz82RkX7WkkF+mvl4iI3LnLO8j4rRUuRiIrdzdjyuGZzPrFFVdXs4NJQaciIyIidybuAOkrHsHVdoV1Bxszdsc8Zs/1wN3d7GBSGKjIiIhI9iUcJ215M9ys59l6rB5D/1jML/O98fAwO5gUFioyIiKSPUmnSVvWFLeMM+w9XZX3I5fx83w/vLzMDiaFiS6GExGR23dlN+mLw3FLO86R6LsZsOQ3Zs4tTpEiZgeTwkZFRkREbk90JBlL78M1/TT7z1Smz7xIps8Jxs/P7GBSGKnIiIhI1h2fhjWyJS5GPGsP3E/fJev5cU4oAQFmB5PCSufIiIjIvzMMjL3Dsex6B2dg1saOzDk7lXlLPPD0NDucFGYqMiIi8s9sGdi29MHp6NcAjFw8gNPFRzB9lpPu2Cum06ElERG5tYxErKufwuno19hsFl774Uuc6o1k9BiVGMkfNCIjIiI3lxJL+m+P4Rq/meQ0D7p+M412rz9Fp05mBxP5fyoyIiLyd/GHSV/ZEtfUY1y8GsAzkxby7phGPPCA2cFEMlORERGRzM5vID3iMVxtFzkWG8ZLPy1l/LRKVKlidjCRv1ORERGR/3dqHtbfO+NKCluO1uedFYuYtjCQ4GCzg4ncnIqMiIhcc3AcxtbXcLYYLNrehm8PzGLuUm98fMwOJnJrKjIiIoWdYcPY/jaWA59jscCkiJ5scxrP7DkuuLqaHU7kn6nIiIgUZtZUrH90w/nUTADemfUpHvUGMel9CxaLydlEskBFRkSksEq7TEbkk7hcWkN6hgs9vvueJi88R7duZgcTyToVGRGRwijxJOkrW+OatI+4JF+enTSHPp825ZFHzA4mcntUZERECpvLO66VmIxznL5Uiq6TlzDqu5rUrm12MJHbpyIjIlKYnFtBxup2uBoJ7D5VndfnLmXK3NKEhpodTCR7VGRERAqLY1OwbeiBiyWDyL0P8cWWOfy61J+iRc0OJpJ92Xpo5NSpU1m8eLH9/Ztvvom/vz+NGjXi5MmTORZORERygGFg7P4INr6AkyWDn9Z1YfKJZfy6UCVGHF+2iszQoUPx9PQEYMOGDYwfP54RI0ZQvHhx+vXrl6MBRUTkDtjSsW3sgWX3YACGzh/EHt8fmfqjG+7uJmcTyQHZOrR06tQpypcvD8C8efNo164dPXv2pHHjxjRp0iQn84mISHalJ5CxpgMuscuw2pzoM3U81Z/sxTuvmB1MJOdka0TGx8eHixcvArBixQqaN28OgIeHB8nJyTmXTkREsic5mvRlD+ISu4ykVE86jZ9Hi1d78YpKjBQw2RqRad68OS+99BJ16tTh0KFDtG7dGoC9e/dStmzZHA0oIiK3KW4/6Stb4Zp2kti4Ejz77SI+ntCAhg3NDiaS87I1IjN+/HjCw8M5f/48v/76K8WKFQNg27ZtPPPMMzkaUEREbkPs76QvbYxr2kkOnatA58kbmDBLJUYKLothGEZ2PpiSksKuXbuIjY3FZrNlmvf444/nSLicEB8fj5+fH3Fxcfj6+podR0Qk90TNxrruOZxJZcPhe/lw9UJ+/Lk4JUqYHUzk9mV1/52tQ0vLli3j+eef5+LFi/y1B1ksFqxWa5bWM3HiRCZOnMiJEycAqFatGh988AGtWrUCrpWlAQMGMHPmTFJTU2nRogUTJkwgMDAwO7FFRAquA6Phz/44A3O3tGVG1DTmLPbCy8vsYCK5K1uHlvr06UOHDh04e/YsNpst0yurJQagdOnSDB8+nG3btrF161YefvhhnnjiCfbu3QtAv379WLhwIbNnz2bNmjWcPXuWp556KjuRRUQKJpsV25a+8Gd/AL5a/iqrMn5hxs8qMVI4ZOvQkq+vL9u3b+fuu+/O8UABAQF8/vnntG/fnhIlSjB9+nTat28PwIEDB6hSpQobNmzg3nvvvennU1NTSU1Ntb+Pj4+nTJkyOrQkIgVPRvK1Q0lnfwVg4LTPCXpoAAMGWLBYTM4mcoeyemgpWyMy7du3Z/Xq1dnNdlNWq5WZM2eSmJhIeHg427ZtIz09nWbNmtmXqVy5MqGhoWzYsOGW6xk2bBh+fn72V5kyZXI0p4hIvpB6kfQVzXA++yup6W50mTiT+s8NZOBAlRgpXLJ1jsy4cePo0KEDv//+OzVq1MDV1TXT/Ndeey3L69q9ezfh4eGkpKTg4+PD3LlzqVq1Kjt27MDNzQ1/f/9MywcGBhIdHX3L9Q0aNIj+/fvb318fkRERKTASjpG2ohVuKYe4nOjPs9/M582RD/Dgg2YHE8l72SoyM2bMYMWKFXh4eLB69WosN9R/i8VyW0WmUqVK7Nixg7i4OH755Re6du3KmjVrshMLAHd3d9x1320RKagubiX9tza4WWM5eSGU7j8uZezUqlStanYwEXNkq8i8++67fPjhh7z99ts4OWXr6JSdm5ub/XEH9erVY8uWLXz55Zd06tSJtLQ0rly5kmlUJiYmhqCgoDv6ThERh3RmMRlrOuJKEttP1OatJYv5YX4IISFmBxMxT7ZaSFpaGp06dbrjEnMzNpuN1NRU6tWrh6urKxEREfZ5Bw8eJCoqivDw8Bz/XhGRfO3IN9hWP44LSSzf9Qgf/bGWX5eqxIhka0Sma9euzJo1i3feeeeOvnzQoEG0atWK0NBQrl69yvTp01m9ejXLly/Hz8+P7t27079/fwICAvD19aVPnz6Eh4ff8oolEZECxzAwdr2PZe+nOFng+9UvsME6iZ/nuvKX0xNFCqVsFRmr1cqIESNYvnw5NWvW/NvJvl988UWW1hMbG8vzzz/PuXPn8PPzo2bNmixfvtz+EMrRo0fj5OREu3btMt0QT0SkULCmYd3YA+eTPwAw5NfBWGoO5psPdGWSyHXZuo/MQw89dOsVWixERkbeUaicpEcUiIhDSosjfXV7XC/8RobVmZcnTyL82e68+KLZwUTyRq4+omDVqlXZDiYiIv8i6QxpK1vjlriLhBRvnvvmF3p92JIWLcwOJpL/ZKvIiIhILrmy59o9YjJOc+5yEF0nL+az/9alTh2zg4nkTyoyIiL5Rcwq0iOfxM2IY/+ZyvSZs5Tvfi1H2bJmBxPJv1RkRETygxPTsa7vhqslnbUH7mfExnnMXhJA0aJmBxPJ31RkRETMZBgY+z7DsnMQzhaYtbEjiy5M5deFHugm5SL/TkVGRMQsNiu2LX1wOjoRgJGLB3C+1Aim/uRELtxvVKRAUpERETFDRhIZazvjEr0Am81Cv5/GUOHR1/jsVbODiTgWFRkRkbyWEkv6b4/hGr+Z5DQPXvjvNDoNfIonnzQ7mIjjUZEREclL8YdJW9kKt9SjXLwawLPfLuSDsY3QI+REskdFRkQkr1zYSPpvj+Fmu8Cx2DD+M2MpE6ZXokIFs4OJOC4VGRGRvHB6Pta1T+NKCluO1ueDyEVMWxhIyZJmBxNxbCoyIiK57dB4jC19cLYYLNrehh+OzuLXxd54eZkdTMTxqciIiOQWw4axfRCWAyOwWGBSRE92u49nxmwXnJ3NDidSMOhOBSIiucGaivX3LlgOjADgnVmfcqXi13w1XiVGJCdpREZEJKelXSY94klcL68hPcOFnt9/T/Oez/HMM2YHEyl4VGRERHJSYtS1p1cn7yMuyZfn/juH/p81pUkTs4OJFEwqMiIiOeXyDtJWtMbNeo7Tl0rx4g9LGD25JtWqmR1MpOBSkRERyQnnVpCxqh1uJLD7VHUGLFzKlHmlCQkxO5hIwaYiIyJyp45NwbahBy6WDCL3PsRXO+fwyxJ/fH3NDiZS8KnIiIhkl2Fg7PkEy+4PcLLAT+u6sCr5e36e64arq9nhRAoHXX4tIpIdGclYN3THsvsDAIbOH8ThEj/y7fcqMSJ5SSMyIiK3K/4Q6as74pqwE6vNiT5Tx1Pv6V507252MJHCR0VGROR2nJxFxh8v4WokEBNXku7fT6P3R81o1crsYCKFk4qMiEhWWFOwbe2P09GJuACr9z3IRxEzmPBjMJUrmx1OpPBSkRER+TdXj5K2qgNuCdux2SwMXfAOZ4oOYXGkC56eZocTKdx0sq+IyD+J+pX0hXVxS9jO+fjiPPXVUso/9QkTJ6nEiOQHGpEREbkZayrWbW/gfOQrXIHfD9zHJ6tmMO6n0lSoYHY4EblORUZE5K8SjpMa2Qn3hC0ADF/wFmeLf8L8lS54eJicTUQy0aElEZEbnZ5P2oK6uCds4eLVADpOWESFDsMZO04lRiQ/0oiMiAiANQ3rn2/jfHg0bsAfh8IZ9vtMvvwhlLvuMjuciNyKioyISGIUKREd8UjYBMDIxQOIDhrGr0tdcXMzOZuI/CMVGREp3M4sIm3N83hwmcuJ/vT+aSpPD3icgY+bHUxEskJFRkQKJ1s6GdvexeXw57gBm4404LP1sxj9QznKljU7nIhklYqMiBQ+SadJ/u1pPBPWAzBm6evElhrBrEV64KOIo1GREZHC5ewyUlc/iycXuZLoR9+Z39Np4FP01bOSRBySioyIFA62DNL/HIzroaG4A9uO12XEH7P54oe7KFXK7HAikl0qMiJS8CWdJem3znglrAVg/IrenA8dxbT57rjoX0ERh6b/hEWkYDu3kuTILnhZzhOfXIQBP39Lx4Ed6d3c7GAikhNUZESkYLJZSdv+ES4HPsbTYrD9RG1Gb/mZz6ZUIDjY7HAiklNUZESk4EmOJmFlF3wSIsECkyL+w4VyY5j8iwfOzmaHE5GcpCIjIgWKEb2K5IjO+FhiSEjx5q1fv6HDG8/wnyZmJxOR3KAiIyIFg81K6vahuB4YgpfFxu5T1fly62yGTq5MyZJmhxOR3KIiIyKOLyWWq8ufpUjiSrDAd6u7c/nusXwzywsnJ7PDiUhuUpEREYdmxKwlaWVnijidJTHFi3fnT6T9G89z331mJxORvKAiIyKOybCR8udnuB14D28nG3tPV2X8ztl8/H1VihUzO5yI5BUVGRFxPCkXiFv2PH5JS8ECP657nssVJjD+J28sFrPDiUheMvXo8bBhw7jnnnsoUqQIJUuWpG3bthw8eDDTMikpKfTu3ZtixYrh4+NDu3btiImJMSmxiJjNiF3P1dl18EtaSnKaB2/8+h0Vn5/Ca/1UYkQKI1OLzJo1a+jduzcbN25k5cqVpKen88gjj5CYmGhfpl+/fixcuJDZs2ezZs0azp49y1NPPWViahExhWEjadvn2FY8SBHn0xw4W4m3V23mnW9fpOG9ajAihZXFMAzD7BDXnT9/npIlS7JmzRoeeOAB4uLiKFGiBNOnT6d9+/YAHDhwgCpVqrBhwwbuvffef11nfHw8fn5+xMXF4evrmyM5DZuNpLgLObIuEcmCtMuk/N6HYmkrAfh501NcKPM5z7/oo1EYkXzAy684lhy+RDCr++98dY5MXFwcAAEBAQBs27aN9PR0mjVrZl+mcuXKhIaG3rLIpKamkpqaan8fHx+f4zmT4i7gHRCY4+sVkZsoD/QB7+JAGvADdFw1B5gDb5gbTUSuSbwUg3dRc27YlG/usGCz2ejbty+NGzemevXqAERHR+Pm5oa/v3+mZQMDA4mOjr7peoYNG4afn5/9VaZMmdyOLiK5pSXwPlAciAaGAKvMDCQi+U2+GZHp3bs3e/bsYd26dXe0nkGDBtG/f3/7+/j4+BwvM15+xUm8pBOORXJN+hUS1/SlZPpSAOZseZyL5b6g859FdChJJB/y8itu2nfniyLz6quvsmjRItauXUvp0qXt04OCgkhLS+PKlSuZRmViYmIICgq66brc3d1xd3fP1bwWJyfThtBECjrbha3EL+tASZcTpKa7MXzFaNq+8TJP1VaDEZG/M/XQkmEYvPrqq8ydO5fIyEjCwsIyza9Xrx6urq5ERETYpx08eJCoqCjCw8PzOq6I5CbD4OrWr7AubYS/ywmOxtzFx5v+oP/Xr1BLJUZEbsHUEZnevXszffp05s+fT5EiReznvfj5+eHp6Ymfnx/du3enf//+BAQE4OvrS58+fQgPD8/SFUsi4iDS4ohd9BIlU34BZ5i37SkSqn3Hx+P9dShJRP6RqZdfW27xL9TkyZPp1q0bcO2GeAMGDGDGjBmkpqbSokULJkyYcMtDS3+VG5dfi0jOsZ7/k7jFHQlwO0pahisjI0byxBt9qFZdDUakMMvq/jtf3UcmN6jIiORThkHcn5Pw3Pc6bs5pnDhflh+P/0z/Txvg7W12OBExm0PeR0ZECon0q0Qv6ElQ6kxwhkU7HiexxhTef72o2clExMGoyIhInsq4sIvLCzsQ5H6I9AwXxqz5jMcG9qNyFR1KEpHbpyIjInnDMLi09Tu89/ehhHsKURfKMOPULF4bF46np9nhRMRRqciISO5LT+DMvJcplf4TuMDy3a1JrPkDb71WzOxkIuLgVGREJFelX9jDpQUdKOVxgAyrM+PXD6XNgIGUr5BvnpAiIg5MRUZEcs3FLVPw3vcKgR7JnL5Uil/OzeTlL+8jl2++LSKFiIqMiOS8jCSi5vQmNGMKuMJve1uQUvdH+r5awuxkIlLAqMiISI5Ku7Cfi/M6EOq1F6vNiW82fETLAYMIu0uHkkQk56nIiEiOid30Ez77exHslci5y0HMjZ3BS6Ob4OZmdjIRKahUZETkzmUkc/yX1wizfQtusPpAU1LrTeOV3oFmJxORAk5FRkTuSOr5Q5yf14Ew713YbBa+3zqYR/q9R2hZZ7OjiUghoCIjItl2buNMfA/0oLR3AjFxJVlwcTrdPm+Kq6vZyUSksFCREZHbln7lBCfn9qO8+zxwg3WHm5B+z3R6vBxsdjQRKWRUZEQk66wpHFv8OSGXh1LePYUMqzPTdrxDs34fUKq0/jkRkbynf3lEJEsu7FxMxubXucv7KLheG4WJLj2O5z6vhpOurBYRk6jIiMg/Sr10nJNz+lLRawF4w5lLIay4MIq2r3XivgA9sVpEzKUiIyI3l5HM4YUjKBM/nIpeKaRnuDB7dz9qdH6fF+oWMTudiAigIiMiNxG9bSFse50KPsfBFdYeasqV8l/ReUQVLBqEEZF8REVGROySzx8lau7rVPJZDD5w+lIpVsWN5ol+7fH1U4MRkfxHRUZEMNKTODh3OGHJI6jkk0pahitz9vWn9rPv8Vx1H7PjiYjckoqMSGFmGJzZvADnHX2pXOTE/w4jNSe52ld0GlZJh5FEJN9TkREppBKij3B63mtU9l0KRSDqYhnWJ4/miTeewstbDUZEHIOKjEghY6QnsXf2UCpkfE5l3zTSMlyZd3Ag9Z5/l86VvM2OJyJyW1RkRAoLw+DEurl47OtH9SJR4AJrD7fAWnssHT+taHY6EZFsUZERKQTiTx/izII+VPFf8b/DSKFsto7h0Tfb4uGpw0gi4rhUZEQKMFtaIrtnfkoVRlLFP53UdDcWHX2DBi+8Q/swL7PjiYjcMRUZkYLIMDiyeg4+h/pRq8gpANYeaYVLwy9p17WCyeFERHKOioxIAXP55EHOLexD1YCVUAROXCjHTucxtH77cVzddBhJRAoWFRmRAsKaksDO6Z9Q3eULqgakk5LmztKot7j3xbd5orSn2fFERHKFioyIozMMDqycjf+xAdT1PQ3AmiOP4n3/GJ7sdrfJ4UREcpeKjIgDO39kP7FL+lCteAT4wokLYez1+JKW7z6Gs7PZ6UREcp+KjIgDSk+6ys5pH1HLYwwlimeQnObByjNvE979TdoE6TCSiBQeKjIijsQw2LNkFiVODaC+71kA1h57DP+Hx/B4t7tMDicikvdUZEQcxLn9e7m4og/VS6z632GkuzjkO5Zm77TBycnsdCIi5lCREcnnUq7Gs+OnD6nnPZbgEtcOI0XGvEOj7m/wSHEPs+OJiJhKRUYkvzIMts+bTkjMG9zrdw6A34+3pXiL0bTpVs7cbCIi+YSKjEg+dGr3buIiXqVOybXgC8fPl+dkia948J2WWHRPOxEROxUZkXwkKS6OHT8MoYH/V5QpaSUp1ZO1l96lcfeBhPm7mx1PRCTfUZERyQcMm8GWX6ZR7vJAGhWLAeD3E08R3OYLWtYqa3I6EZH8S0VGxGTH/txFwupXaRD0OxSBo+crEl3qK+4b9IgOI4mI/AsVGRGTxF+8ws4fBxNebDwuQVYSU734I/59Gr/Yj7uL6DCSiEhWqMiI5DHDZmPD9B+pkPgm95eMBWD9qfaUfvwLmlcpY3I6ERHHoiIjkocObtxB2vreNAr+43+HkSpxsdxXNH6rudnRREQckoqMSB64EnuFnT++z32BE3AOtpGQ4s3m5A9o3LMvd3u6mR1PRMRhqciI5CKb1cbvP0ylatpbPBh8HoA/znSk3JOjeLh8aZPTiYg4PhUZkVyyZ+2fGFt682DwRnCHo+ercLXSVzR6pqnZ0URECgxTHzW3du1aHnvsMUJCQrBYLMybNy/TfMMw+OCDDwgODsbT05NmzZpx+PBhc8KKZNGFs5dYNeIVqkbVp0bwRq6m+LD26ueE9tpB7ZYqMSIiOcnUIpOYmEitWrUYP378TeePGDGCsWPH8vXXX7Np0ya8vb1p0aIFKSkpeZxU5N9lpNuI/O+3sLASD5WeiJOTwYZznUlueoAH/jMQV3edCyMiktMshmEYZocAsFgszJ07l7Zt2wLXRmNCQkIYMGAAAwcOBCAuLo7AwECmTJnC008/naX1xsfH4+fnR1xcHL6+vrkVXwq5P3/biuuO3tQI2QzAkQvVSKk2jupNm5gbTETEQWV1/23qiMw/OX78ONHR0TRr1sw+zc/Pj4YNG7Jhw4Zbfi41NZX4+PhML5Hccu7kRSKG96J2dANqhGzmanIR/kgZRdjL21ViRETyQL4tMtHR0QAEBgZmmh4YGGifdzPDhg3Dz8/P/ipTRjcYk5x34Vw8y8aMxn15RZqGTsLJyWBTTBfSWh6k0Yv9cXZ1NTuiiEihUOCuWho0aBD9+/e3v4+Pj1eZkRxzdPcpji4ZS8Ni39Cy5LXRviMXamCtM46GzzxgcjoRkcIn3xaZoKAgAGJiYggODrZPj4mJoXbt2rf8nLu7O+7uek6N5BzDgO2Rf3J18ygalfqZu8tkAHDiUiUulBhA3VdewMkl3/6nJCJSoOXbf33DwsIICgoiIiLCXlzi4+PZtGkTL7/8srnhpFDISLex4dcleJ4cRf0yq6Hstem7Yh7CqdoAqj3dinJO+fborIhIoWBqkUlISODIkSP298ePH2fHjh0EBAQQGhpK3759+eSTT6hQoQJhYWG8//77hISE2K9sEskNCXHJbJr5I+VSvuD+EgehDKRnuPDnxU4ENulPzWfqmh1RRET+x9Qis3XrVh566CH7++vntnTt2pUpU6bw5ptvkpiYSM+ePbly5Qr33Xcfy5Ytw8PDw6zIUoBFn4hl79zx1PKaQNMiF6AIxCf7sjv5P1R+og8Nda6ViEi+k2/uI5NbdB8Z+TeHtuzn3KovaBj4Ix6uqQCcvlKWKM++1GnXHU/fIiYnFBEpfLK6/86358iI5CbDZrBt6Sqse0fRsPQSKv7v+Y37YhqQFDqAuj2forRO4BURyff0L7UUKmkp6WyaPYvi57+gftB2KA02m4WtMU/gU38AVTs3BovF7JgiIpJFKjJSKMSdv8Kfs7+hMmO53/8MBEFSmifbLr9AuRZ9aVC1gtkRRUQkG1RkpEA7feAER5eMoa7/dzzknwBAbHwgB2x9qNmuF/cHFjM5oYiI3AkVGSmQ9v++iSsbR9Eg+FdKB9kAOBxbndiA/tzT9Rke8NRNE0VECgIVGSkwbBlWti1YgMeJUdQIWg+lrk3fdqY5VBlA3acfoYKTzn8RESlIVGTE4aUkJLJt9hRKJYzhnmJHIAjSMlzZFPMMJR/oT71napodUUREcomKjDisi2fOsW/uOKq5f01j70vgDpcTi7I9oReVH3+V++8OMTuiiIjkMhUZcTgnduzmbOQX1Cs2nfsD0gA4efEujrn1o37HF3i4qLfJCUVEJK+oyIhDMGwGeyNWkr57FHWCVlDu2sPR2Xm2EVdLD+De/zxBWTdnc0OKiEieU5GRfC0jNZU/580gIOYLqhffDUFgtTmx8fRTeNUbQO3O9+r+dSIihZiKjORLCZcusXvO19xt/YoGRaKhOCSkeLPpQnfKtehL42fDzI4oIiL5gIqM5CuxR49wdMkYavpMJtwrCYBzV0LYk/4atdv3pGmpoiYnFBGR/ERFRsxnGBzb/AeX/xhFnRLzKFns2gPZ952rzTn/AYQ/35HmPm4mhxQRkfxIRUZMY1gz2L10Lm5HR1G5xCYIvDZ9w8nWWCsOIPz1h6jqohNgRETk1lRkJM+lJ11lx5zvCYkfQ03/E1ACUtLcWXf2OUrc14/wZ6qaHVFERByEiozkmfjo0xyYP5ZKLt9wj2cc+MP5q8XZGvcKVR9/hWaVA82OKCIiDkZFRnLd2b3bORc5ipr+s2hQJAOAI7EVOezcn4ZPP0+rEp4mJxQREUelIiO5w7BxeO1S0naOolrxVYQUuzZ5y8kHiQsZwP292lDew8ncjCIi4vBUZCRH2dJT2LPoR3zPjqZC0f1QHDKszqw90RGPOgMIf7uebmAnIiI5RkVGckRK3Hn2zp1AufTx1PQ+D0UhLsmX9dE9KNviNR5+LtTsiCIiUgCpyMgduXzyIMeWfEFVzx+o55YCbhB1MZSdKa9Tt8NLtC7na3ZEEREpwFRk5LYlnT/Jkd+X4nRmHtWLLaee37XpO0/V53SRAdz/XHse89dfLRERyX3a28i/MqzpnNq+ntjtSyietoRyRfdSE6AY2GwW1h57nIzy/Xmw3/3UctMJMCIikndUZOSmki6e4/CapdhOL6G8z0pCPeIJ9Qa8rz19+s+oRpylNUEN2vNglwo6gVdEREyhIiMAGFYrp3Zu4ty2JQSkLKFCse3UAih+bX5sfAl2xLYivXhrKjzwCPW7FFV5ERER06nIFGJJly9wcPVyMqKWUN57GaFel+yjLjabhV1n7uG0rTW+VVpT97F6PFJE930REZH8RUWmMDFsRO3czpktS/BPWkKlYpuo42RAiWuzLyf6syOmBSkBbbj7vhbU6lKS2hp1ERGRfExFpoBLunKFA6tXknZiCXd7LiW0SIx91AVg79lanMpojU+l1tR+9F4e8tVfCRERcRzaaxU0hsHJXXs4vXkJvglLqFJ8PXWdrVDy2uyryT7siGlOsn9ryjVqRdXOpaimURcREXFQKjIFQPLVBPZFRpJybDF3eSyhrN9pyt4w6nI4pgon0lrjVaE1Ndvcx/1+bqbmFRERySkqMo7IMDi55zAnNy7BJ24J1UqsoZ5rGgRem52U6snOmIdJ9G1N6L2tqNA5jAoadRERkQJIRcZBJCckszdyDYlHllDObQllA45mGnU5efEujia3wePu1tRo/SDh/p6m5hUREckLKjL52Ml9Jzi+fgleV5ZQvXgk9d2TIejavLQMV3ZFP0i8T2tKN2hNhboVKeukYRcRESlcVGTykZSkNHZHruPqwSWEuiyhfIn9mUZdzl4pzZGk1riVa03Vlg9TP6CIqXlFRETMpiJjspMHznL096V4XFpMjRIruccjAYKvzcuwOrMnpjFXvFsTUr81FepVJ0SjLiIiInYqMnksJSmDXas2Ebd/CaUsS6gavCPTqMv5qyU5lNAal9DWVGnRnNrF/M2MKyIikq+pyOSBk4fOc3jNMlzPL6FGieU08L4MIdfm2WwW9p9vwCWP1gTVbU35e+pSwkmPAhAREckKFZlckJpiY0fkNi7vXUIwS6gRvIWy3oZ91OVyUlEOxbfEUro1lZu0oFrJEuYGFhERcVAqMjkk6shlDqxeiXP0EmoUX0pD31go9f/zD52vw3m31pSs3ZryDRrQ0FmbXkRE5E5pb5pNqSkG21fv5uKuJQRal1C79B+Eelnhrmvzr6YU4VB8c4zgNlR4sCUVg0KoaG5kERGRAkdFJpu2jWlHo9C5UPr/px2/VJUY59YUr9mauxs2pp6LHgUgIiKSm1Rkssnqfw/Jacs4GNcUa2BrKjzQirCQcoSZHUxERKQQsRiGYZgdIjfFx8fj5+dHXFwcvr6+Obbe1IR4XN3dcHL1yLF1ioiIyDVZ3X9rRCab3H1yrhSJiIhI9uiGJSIiIuKwVGRERETEYTlEkRk/fjzlypXDw8ODhg0bsnnzZrMjiYiISD6Q74vMrFmz6N+/P4MHD+bPP/+kVq1atGjRgtjYWLOjiYiIiMny/VVLDRs25J577mHcuHEA2Gw2ypQpQ58+fXj77bf/tnxqaiqpqan29/Hx8ZQpUybHr1oSERGR3JPVq5by9YhMWloa27Zto1mzZvZpTk5ONGvWjA0bNtz0M8OGDcPPz8/+KlOmTF7FFRERkTyWr4vMhQsXsFqtBAYGZpoeGBhIdHT0TT8zaNAg4uLi7K9Tp07lRVQRERExQYG7j4y7uzvu7u5mxxAREZE8kK9HZIoXL46zszMxMTGZpsfExBAUFGRSKhEREckv8nWRcXNzo169ekRERNin2Ww2IiIiCA8PNzGZiIiI5Af5/tBS//796dq1K/Xr16dBgwaMGTOGxMREXnjhBbOjiYiIiMnyfZHp1KkT58+f54MPPiA6OpratWuzbNmyv50ALCIiIoVPvr+PzJ3Kradfi4iISO7R06//53pPi4+PNzmJiIiIZNX1/fa/jbcU+CJz9epVAN0YT0RExAFdvXoVPz+/W84v8IeWbDYbZ8+epUiRIlgsFrPjAP//2IRTp07pcNdt0HbLPm277NO2yx5tt+zTtrvGMAyuXr1KSEgITk63vsi6wI/IODk5Ubp0abNj3JSvr2+h/kuaXdpu2adtl33adtmj7ZZ92nb840jMdfn6PjIiIiIi/0RFRkRERByWiowJ3N3dGTx4sJ4JdZu03bJP2y77tO2yR9st+7Ttbk+BP9lXRERECi6NyIiIiIjDUpERERERh6UiIyIiIg5LRUZEREQclopMFqxdu5bHHnuMkJAQLBYL8+bNyzTfMAw++OADgoOD8fT0pFmzZhw+fDjTMpcuXaJLly74+vri7+9P9+7dSUhIyLTMrl27uP/++/Hw8KBMmTKMGDHib1lmz55N5cqV8fDwoEaNGixZsiTHf96cMmzYMO655x6KFClCyZIladu2LQcPHsy0TEpKCr1796ZYsWL4+PjQrl07YmJiMi0TFRVFmzZt8PLyomTJkrzxxhtkZGRkWmb16tXUrVsXd3d3ypcvz5QpU/6WZ/z48ZQrVw4PDw8aNmzI5s2bc/xnzikTJ06kZs2a9htihYeHs3TpUvt8bbesGT58OBaLhb59+9qnadvd3JAhQ7BYLJlelStXts/XdvtnZ86c4dlnn6VYsWJ4enpSo0YNtm7dap+v/UQuMuRfLVmyxHj33XeNOXPmGIAxd+7cTPOHDx9u+Pn5GfPmzTN27txpPP7440ZYWJiRnJxsX6Zly5ZGrVq1jI0bNxq///67Ub58eaNz5872+XFxcUZgYKDRpUsXY8+ePcaMGTMMT09PY9KkSfZl1q9fbzg7OxsjRoww9u3bZ7z33nuGq6ursXv37lzfBtnRokULY/LkycaePXuMHTt2GK1btzZCQ0ONhIQE+zK9evUyypQpY0RERBhbt2417r33XqNRo0b2+RkZGUb16tWNZs2aGdu3bzeWLFliFC9e3Bg0aJB9mWPHjhleXl5G//79jX379hlfffWV4ezsbCxbtsy+zMyZMw03Nzfj+++/N/bu3Wv06NHD8Pf3N2JiYvJmY9ymBQsWGIsXLzYOHTpkHDx40HjnnXcMV1dXY8+ePYZhaLtlxebNm41y5coZNWvWNF5//XX7dG27mxs8eLBRrVo149y5c/bX+fPn7fO13W7t0qVLRtmyZY1u3boZmzZtMo4dO2YsX77cOHLkiH0Z7Sdyj4rMbfprkbHZbEZQUJDx+eef26dduXLFcHd3N2bMmGEYhmHs27fPAIwtW7bYl1m6dKlhsViMM2fOGIZhGBMmTDCKFi1qpKam2pd56623jEqVKtnfd+zY0WjTpk2mPA0bNjT+85//5OjPmFtiY2MNwFizZo1hGNe2k6urqzF79mz7Mvv37zcAY8OGDYZhXCuRTk5ORnR0tH2ZiRMnGr6+vvZt9eabbxrVqlXL9F2dOnUyWrRoYX/foEEDo3fv3vb3VqvVCAkJMYYNG5bzP2guKVq0qPHtt99qu2XB1atXjQoVKhgrV640HnzwQXuR0ba7tcGDBxu1atW66Txtt3/21ltvGffdd98t52s/kbt0aOkOHT9+nOjoaJo1a2af5ufnR8OGDdmwYQMAGzZswN/fn/r169uXadasGU5OTmzatMm+zAMPPICbm5t9mRYtWnDw4EEuX75sX+bG77m+zPXvye/i4uIACAgIAGDbtm2kp6dn+pkqV65MaGhopm1Xo0YNAgMD7cu0aNGC+Ph49u7da1/mn7ZLWloa27Zty7SMk5MTzZo1c4htZ7VamTlzJomJiYSHh2u7ZUHv3r1p06bN334+bbt/dvjwYUJCQrjrrrvo0qULUVFRgLbbv1mwYAH169enQ4cOlCxZkjp16vDf//7XPl/7idylInOHoqOjATL9x3v9/fV50dHRlCxZMtN8FxcXAgICMi1zs3Xc+B23Wub6/PzMZrPRt29fGjduTPXq1YFrP4+bmxv+/v6Zlv3rtsvudomPjyc5OZkLFy5gtVodbtvt3r0bHx8f3N3d6dWrF3PnzqVq1arabv9i5syZ/PnnnwwbNuxv87Ttbq1hw4ZMmTKFZcuWMXHiRI4fP87999/P1atXtd3+xbFjx5g4cSIVKlRg+fLlvPzyy7z22mtMnToV0H4itxX4p19L/tC7d2/27NnDunXrzI7iMCpVqsSOHTuIi4vjl19+oWvXrqxZs8bsWPnaqVOneP3111m5ciUeHh5mx3EorVq1sv+5Zs2aNGzYkLJly/Lzzz/j6elpYrL8z2azUb9+fYYOHQpAnTp12LNnD19//TVdu3Y1OV3BpxGZOxQUFATwt7P3Y2Ji7POCgoKIjY3NND8jI4NLly5lWuZm67jxO261zPX5+dWrr77KokWLWLVqFaVLl7ZPDwoKIi0tjStXrmRa/q/bLrvbxdfXF09PT4oXL46zs7PDbTs3NzfKly9PvXr1GDZsGLVq1eLLL7/UdvsH27ZtIzY2lrp16+Li4oKLiwtr1qxh7NixuLi4EBgYqG2XRf7+/lSsWJEjR47o79y/CA4OpmrVqpmmValSxX5oTvuJ3KUic4fCwsIICgoiIiLCPi0+Pp5NmzYRHh4OQHh4OFeuXGHbtm32ZSIjI7HZbDRs2NC+zNq1a0lPT7cvs3LlSipVqkTRokXty9z4PdeXuf49+Y1hGLz66qvMnTuXyMhIwsLCMs2vV68erq6umX6mgwcPEhUVlWnb7d69O9N/4CtXrsTX19f+D8e/bRc3Nzfq1auXaRmbzUZERES+3XY3Y7PZSE1N1Xb7B02bNmX37t3s2LHD/qpfvz5dunSx/1nbLmsSEhI4evQowcHB+jv3Lxo3bvy3W0scOnSIsmXLAtpP5DqzzzZ2BFevXjW2b99ubN++3QCML774wti+fbtx8uRJwzCuXVbn7+9vzJ8/39i1a5fxxBNP3PSyujp16hibNm0y1q1bZ1SoUCHTZXVXrlwxAgMDjeeee87Ys2ePMXPmTMPLy+tvl9W5uLgYI0eONPbv328MHjw4X19W9/LLLxt+fn7G6tWrM13SmZSUZF+mV69eRmhoqBEZGWls3brVCA8PN8LDw+3zr1/S+cgjjxg7duwwli1bZpQoUeKml3S+8cYbxv79+43x48ff9JJOd3d3Y8qUKca+ffuMnj17Gv7+/pmusMhP3n77bWPNmjXG8ePHjV27dhlvv/22YbFYjBUrVhiGoe12O268askwtO1uZcCAAcbq1auN48ePG+vXrzeaNWtmFC9e3IiNjTUMQ9vtn2zevNlwcXExPv30U+Pw4cPGtGnTDC8vL+Onn36yL6P9RO5RkcmCVatWGcDfXl27djUM49qlde+//74RGBhouLu7G02bNjUOHjyYaR0XL140OnfubPj4+Bi+vr7GCy+8YFy9ejXTMjt37jTuu+8+w93d3ShVqpQxfPjwv2X5+eefjYoVKxpubm5GtWrVjMWLF+faz32nbrbNAGPy5Mn2ZZKTk41XXnnFKFq0qOHl5WU8+eSTxrlz5zKt58SJE0arVq0MT09Po3jx4saAAQOM9PT0TMusWrXKqF27tuHm5mbcddddmb7juq+++soIDQ013NzcjAYNGhgbN27MjR87R7z44otG2bJlDTc3N6NEiRJG06ZN7SXGMLTdbsdfi4y23c116tTJCA4ONtzc3IxSpUoZnTp1ynQfFG23f7Zw4UKjevXqhru7u1G5cmXjm2++yTRf+4ncYzEMwzBnLEhERETkzugcGREREXFYKjIiIiLisFRkRERExGGpyIiIiIjDUpERERERh6UiIyIiIg5LRUZEREQcloqMiIiIOCwVGREREXFYKjIiIiLisFRkRERExGG5mB1AROR2NWnShJo1a+Lh4cG3336Lm5sbvXr1YsiQIWZHE5E8phEZEXFIU6dOxdvbm02bNjFixAg++ugjVq5caXYsEcljevq1iDicJk2aYLVa+f333+3TGjRowMMPP8zw4cNNTCYieU0jMiLikGrWrJnpfXBwMLGxsSalERGzqMiIiENydXXN9N5isWCz2UxKIyJmUZERERERh6UiIyIiIg5LRUZEREQclq5aEhEREYelERkRERFxWCoyIiIi4rBUZERERMRhqciIiIiIw1KREREREYelIiMiIiIOS0VGREREHJaKjIiIiDgsFRkRERFxWCoyIiIi4rBUZERERMRh/R/Sa9PcfMwK+QAAAABJRU5ErkJggg==",
      "text/plain": [
       "<Figure size 640x480 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "backward:\n",
      "         n  triton-v1  Torch  Flex  triton-v2\n",
      "0   8192.0   1.468365   20.0  20.0   1.453358\n",
      "1  16384.0   4.689148   20.0  20.0   4.708893\n",
      "2  24576.0   9.772910   20.0  20.0   9.762478\n",
      "3  32768.0  16.450586   20.0  20.0  16.493933\n",
      "4  40960.0  24.828651   20.0  20.0  24.978943\n",
      "5  49152.0  34.734112   20.0  20.0  34.892048\n",
      "6  57344.0  46.322624   20.0  20.0  46.735138\n",
      "7  65536.0  59.762367   20.0  20.0  60.145855\n"
     ]
    }
   ],
   "source": [
    "torch.cuda.empty_cache()\n",
    "@triton.testing.perf_report(\n",
    "    triton.testing.Benchmark(\n",
    "        x_names=['n'],  # argument names to use as an x-axis for the plot\n",
    "        x_vals=[8192 * i for i in range(1, 8+1)],  # different possible values for `x_name`\n",
    "        line_arg='provider',  # argument name whose value corresponds to a different line in the plot\n",
    "        line_vals=['triton-v1', 'torch', 'flex', 'triton-v2'],  # possible values for `line_arg``\n",
    "        line_names=[\n",
    "            \"triton-v1\",\n",
    "            \"Torch\",\n",
    "            \"Flex\",\n",
    "            \"triton-v2\",\n",
    "        ],  # label name for the lines\n",
    "        styles=[('blue', '-'), ('green', '-'), ('red', '-'), ('orange', '-')],  # line styles\n",
    "        ylabel=\"ms\",  # label name for the y-axis\n",
    "        plot_name=\"backward\",  # name for the plot. Used also as a file name for saving the plot.\n",
    "        args={'b':1, 'qh':64, 'kh':4, 'd':128, 'vd':128, 'stride':16, 'kernel_size':32},  # values for function arguments not in `x_names` and `y_name`\n",
    "    ))\n",
    "def benchmark(b, qh, kh, n, d,vd, stride, kernel_size, provider):\n",
    "    device = 'cuda'\n",
    "    dtype = torch.bfloat16\n",
    "    num_blocks = (n - kernel_size) // stride + 1\n",
    "    q = torch.randn(b, n, qh, d, device=device, dtype=dtype)\n",
    "    ck = torch.randn(b, num_blocks, kh, d, device=device, dtype=dtype)\n",
    "    cv = torch.randn(b, num_blocks, kh, vd, device=device, dtype=dtype)\n",
    "    q.requires_grad_(True)\n",
    "    ck.requires_grad_(True)\n",
    "    cv.requires_grad_(True)\n",
    "    stream = torch.cuda.Stream()\n",
    "    torch.cuda.set_stream(stream)\n",
    "    if provider == 'torch':\n",
    "        if n > 4096:\n",
    "            return 20\n",
    "        y = torch_cmp_attn(q, ck, cv, kernel_size, stride)\n",
    "        dy = torch.randn_like(y)\n",
    "        ms = triton.testing.do_bench(lambda: y.backward(dy, retain_graph=True), grad_to_none=[q, ck, cv])\n",
    "    if provider == 'triton-v1':\n",
    "        y, _ = triton_compress_attn_v1(q, ck, cv, kernel_size, stride)\n",
    "        dy = torch.randn_like(y)\n",
    "        ms = triton.testing.do_bench(lambda: y.backward(dy, retain_graph=True), grad_to_none=[q, ck, cv])\n",
    "    if provider == 'triton-v2':\n",
    "        y, _ = triton_compress_attn_v2(q, ck, cv, kernel_size, stride)\n",
    "        dy = torch.randn_like(y)\n",
    "        ms = triton.testing.do_bench(lambda: y.backward(dy, retain_graph=True), grad_to_none=[q, ck, cv])\n",
    "    if provider == 'flex':\n",
    "        if n > 4096:\n",
    "            return 20\n",
    "        if not math.log2(d).is_integer():\n",
    "            return 10\n",
    "        y = flex_cmp_attn(q, ck, cv, kernel_size, stride)\n",
    "        dy = torch.randn_like(y)\n",
    "        ms = triton.testing.do_bench(lambda: y.backward(dy, retain_graph=True), grad_to_none=[q, ck, cv])\n",
    "    return ms\n",
    "benchmark.run(show_plots=True, print_data=True)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Select_attn"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "import torch\n",
    "import triton\n",
    "import math\n",
    "from copy import deepcopy\n",
    "import os\n",
    "os.environ['TRITON_PRINT_AUTOTUNING'] = '1'\n",
    "from torch_code import torch_select_for_fwd, torch_select_attn\n",
    "from select_attn import select_for_fwd_bwd\n",
    "from select_attn import select_attn as triton_select_attn_v1\n",
    "from select_attn_v2 import select_attn as triton_select_attn_v2\n",
    "from select_attn_v3 import select_attn as triton_select_attn_v3\n",
    "# from exp_family import _attention, select_attn"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## select"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "n = 8192\n",
    "kernel_size = 32\n",
    "stride = 16\n",
    "select_size = 64\n",
    "top_n = 16\n",
    "# flex_attn必须要head_dim是2的指数倍\n",
    "b, qh, kh, d, vd = 1, 64, 4, 128, 128\n",
    "device = 'cuda'\n",
    "dtype = torch.bfloat16\n",
    "num_blocks = (n - kernel_size) // stride + 1\n",
    "q = torch.randn(b, n, qh, d, device=device, dtype=dtype)\n",
    "ck = torch.randn(b, num_blocks, kh, d, device=device, dtype=dtype)\n",
    "lse = torch.rand(b, qh, n, device=device, dtype=torch.float32) + 4"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "tensor(1., device='cuda:0') tensor(0.0085, device='cuda:0')\n",
      "tensor(0.0003, device='cuda:0')\n"
     ]
    }
   ],
   "source": [
    "p1, ind1 = torch_select_for_fwd(q, ck, lse, kernel_size, stride, select_size, top_n)\n",
    "# select操作是不可导的，写前向就行了\n",
    "p2, ind2 = triton_select_for_fwd(q, ck, lse, kernel_size, stride, select_size, top_n, return_p=True)\n",
    "print((p1 - p2).abs().max(), (p1 - p2).abs().mean())\n",
    "print(((p1 - p2).abs() / (p2.abs() + 1e-3)).mean())"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "45.77288055419922\n",
      "0.2832818627357483\n"
     ]
    }
   ],
   "source": [
    "print(triton.testing.do_bench(lambda: torch_select_for_fwd(q, ck, lse, kernel_size, stride, select_size, top_n)))\n",
    "print(triton.testing.do_bench(lambda: triton_select_for_fwd(q, ck, lse, kernel_size, stride, select_size, top_n)))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "tensor([[  0, 128, 128,  ..., 128, 128, 128],\n",
      "        [  0, 128, 128,  ..., 128, 128, 128],\n",
      "        [  0, 128, 128,  ..., 128, 128, 128],\n",
      "        ...,\n",
      "        [127,  56,  12,  ...,  64, 111,  48],\n",
      "        [127,  46,   3,  ..., 123,   4,  66],\n",
      "        [127,   7,   1,  ...,  94,  80,  73]], device='cuda:0')\n",
      "tensor([[  0, 128, 128,  ..., 128, 128, 128],\n",
      "        [  0, 128, 128,  ..., 128, 128, 128],\n",
      "        [  0, 128, 128,  ..., 128, 128, 128],\n",
      "        ...,\n",
      "        [127,  56,  12,  ...,  64, 111,  48],\n",
      "        [127,  46,   3,  ..., 123,   4,  37],\n",
      "        [127,   7,   1,  ...,  80,  94,  73]], device='cuda:0',\n",
      "       dtype=torch.int32)\n"
     ]
    }
   ],
   "source": [
    "# 下面这两个不一定完全一样，p的小误差，可能选的就不一样, 大致差不多\n",
    "# 128类似-100，表示不选，比如[0, 63]最多就选一个block\n",
    "print(ind1[0, 0])\n",
    "print(ind2[0, 0])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "tensor([[   0,    1,    2,  ..., 8189, 8190, 8191],\n",
      "        [  64,   65,   66,  ..., 8189, 8190, 8191],\n",
      "        [ 128,  129,  130,  ..., 8188, 8189, 8190],\n",
      "        ...,\n",
      "        [8064, 8065, 8066,  ..., 8189, 8190, 8191],\n",
      "        [8128, 8129, 8130,  ..., 8125, 8126, 8127],\n",
      "        [   0,    1,    2,  ..., 8189, 8190, 8191]], device='cuda:0')\n",
      "tensor([1861, 2490, 3578, 3055, 2593, 2720, 3240, 1814, 2708, 3632, 2351, 2366,\n",
      "        1774, 1797, 2781, 2029, 2265, 1761, 1310, 2753, 1575, 1521, 1557, 1926,\n",
      "         890, 1945, 1222, 1114, 2090, 1253, 2156, 1297, 1145, 1327, 1843, 1747,\n",
      "        1139,  601, 1713, 1748, 1328,  749, 1294, 1503,  828, 1237,  555,  776,\n",
      "         734,  960, 1198,  742, 1002,  677,  916, 1539,  805, 1046,  668,  525,\n",
      "        1249,  500,  768,  449, 1122,  646,  328,  506,  719,  384,  524,  567,\n",
      "         601, 1010,  649,  450,  467,  648,  526,  290,  703,  319,  641,  674,\n",
      "         437,  329,  504,  454,  512,  310,  295,  289,  207,  271,  363,  474,\n",
      "         409,  368,  494,  245,  437,  365,  296,  282,  280,  244,  154,  235,\n",
      "         272,  127,  110,  147,  269,  175,  194,  159,  143,  130,  112,   91,\n",
      "         109,  107,  105,   97,   74,   77,   67,   64,  960], device='cuda:0')\n"
     ]
    }
   ],
   "source": [
    "# 用于attention反向传播，bwd_ind表示kv block被哪个q选了，count表示个数\n",
    "bwd_ind, counts = select_for_bwd(ind2)\n",
    "print(bwd_ind[0, 0])\n",
    "print(counts[0,0])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## attention"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 精度测试"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [],
   "source": [
    "n = 8192\n",
    "kernel_size = 32\n",
    "stride = 16\n",
    "select_size = 64\n",
    "top_n = 16\n",
    "b, qh, kh, d, vd = 1, 64, 4, 128, 128\n",
    "device = 'cuda'\n",
    "dtype = torch.float16\n",
    "num_blocks = (n-kernel_size) // stride + 1\n",
    "q1 = torch.randn(b, n, qh, d, device=device, dtype=dtype)\n",
    "k1 = torch.randn(b, n, kh, d, device=device, dtype=dtype)\n",
    "v1 = torch.randn(b, n, kh, vd, device=device, dtype=dtype)\n",
    "q1.requires_grad_(True)\n",
    "k1.requires_grad_(True)\n",
    "v1.requires_grad_(True)\n",
    "q2 = deepcopy(q1)\n",
    "k2 = deepcopy(k1)\n",
    "v2 = deepcopy(v1)\n",
    "ck1 = torch.randn(b, num_blocks, kh, d, device=device, dtype=dtype)\n",
    "lse = torch.rand(b, qh, n, device=device, dtype=torch.float32) + 10\n",
    "_, fwd_ind, bwd_ind = select_for_fwd_bwd(q1, ck1, lse, kernel_size, stride, select_size, top_n)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "========== triton vs torch\n",
      "0.0029296875 3.039836883544922e-05\n",
      "0.0078125 9.512901306152344e-05\n",
      "0.03125 0.00036025047302246094\n",
      "0.03125 0.00034499168395996094\n"
     ]
    }
   ],
   "source": [
    "\n",
    "y1 = torch_select_attn(q1, k1, v1, select_size, fwd_ind.to(torch.int64))\n",
    "y2 = triton_select_attn_v3(q2, k2, v2, select_size, fwd_ind, bwd_ind, inplace=False)\n",
    "dy1 = torch.randn_like(y1)\n",
    "dy2 = torch.randn_like(y2)\n",
    "dy2.data.copy_(dy1)\n",
    "y1.backward(dy1)\n",
    "y2.backward(dy2)\n",
    "print('='*10 + ' triton vs torch')\n",
    "print((y1-y2).abs().max().item(), (y1-y2).abs().mean().item())\n",
    "print((q1.grad-q2.grad).abs().max().item(), (q1.grad-q2.grad).abs().mean().item())\n",
    "print((k1.grad-k2.grad).abs().max().item(), (k1.grad-k2.grad).abs().mean().item())\n",
    "print((v1.grad-v2.grad).abs().max().item(), (v1.grad-v2.grad).abs().mean().item())"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### forward"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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T/cud3Tfck/3zrAsi5MnTxIZGYmX14VnwhT4HhkvLy/Kli1rdxjnFRISUqh/SXNL9y33dO9yT/cud3Tfck/3jov2xJyhyb4iIiLisZTIiIiIiMdSImMDf39/hg4dir+/v92heBTdt9zTvcs93bvc0X3LPd27S1PgJ/uKiIhIwaUeGREREfFYSmRERETEYymREREREY+lREZEREQ8lhKZHFi0aBHt2rUjMjISh8PBt99+m+28ZVm89NJLREREEBgYSIsWLdi2bVu2a44fP05MTAwhISEUK1aM7t27k5SUlO2adevWcfPNNxMQEEC5cuUYPXr0P2L5+uuvqVatGgEBAVx33XX89NNPef795pWRI0dyww03ULRoUUqXLk379u2Ji4vLdk1qaip9+/alRIkSBAcHc++993Lo0KFs1+zdu5c77riDoKAgSpcuzdNPP01mZma2axYsWMD111+Pv78/VapUYdKkSf+I591336VixYoEBATQsGFD/vjjjzz/nvPKhAkTqFWrlmtDrOjoaGbNmuU6r/uWM6NGjcLhcDBgwADXMd278xs2bBgOhyPbo1q1aq7zum8Xt3//fh588EFKlChBYGAg1113HStWrHCd1+dEPrLkX/3000/W888/b33zzTcWYM2YMSPb+VGjRlmhoaHWt99+a61du9a68847raioKOvUqVOua26//Xardu3a1tKlS61ff/3VqlKlitW5c2fX+YSEBKtMmTJWTEyMtWHDBuuLL76wAgMDrQ8++MB1zeLFiy1vb29r9OjR1qZNm6wXXnjB8vX1tdavX5/v9yA3WrVqZU2cONHasGGDtWbNGqtNmzZW+fLlraSkJNc1vXv3tsqVK2fNmzfPWrFihXXjjTdajRo1cp3PzMy0atasabVo0cJavXq19dNPP1klS5a0hgwZ4rpm586dVlBQkDVw4EBr06ZN1jvvvGN5e3tbs2fPdl0zbdo0y8/Pz/rkk0+sjRs3Wj179rSKFStmHTp06MrcjEs0c+ZM68cff7S2bt1qxcXFWc8995zl6+trbdiwwbIs3bec+OOPP6yKFStatWrVsp544gnXcd278xs6dKhVo0YN6+DBg67HkSNHXOd13y7s+PHjVoUKFaxu3bpZy5Yts3bu3GnNmTPH2r59u+safU7kHyUyl+jviYzT6bTCw8OtN954w3XsxIkTlr+/v/XF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",
      "text/plain": [
       "<Figure size 640x480 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "forward:\n",
      "         n  triton-v1  torch  triton-v3  triton-v2\n",
      "0   8192.0   3.394512   10.0   1.897318   1.894896\n",
      "1  16384.0   7.006057   10.0   3.872566   3.852431\n",
      "2  24576.0  10.798994   10.0   5.835634   5.848036\n",
      "3  32768.0  14.728879   10.0   7.819782   7.832922\n",
      "4  40960.0  18.751648   10.0   9.842164  10.023431\n",
      "5  49152.0  22.916727   10.0  11.980547  12.023136\n",
      "6  57344.0  27.038763   10.0  14.101783  14.130798\n",
      "7  65536.0  31.376106   10.0  16.385237  16.313532\n"
     ]
    }
   ],
   "source": [
    "torch.cuda.empty_cache()\n",
    "@triton.testing.perf_report(\n",
    "    triton.testing.Benchmark(\n",
    "        x_names=['n'],  # argument names to use as an x-axis for the plot\n",
    "        x_vals=[8192 * i for i in range(1, 8+1)],  # different possible values for `x_name`\n",
    "        line_arg='provider',  # argument name whose value corresponds to a different line in the plot\n",
    "        line_vals=['triton-v1', 'torch', 'triton-v3', 'triton-v2'],  # possible values for `line_arg``\n",
    "        line_names=[\n",
    "            \"triton-v1\",\n",
    "            \"torch\",\n",
    "            \"triton-v3\",\n",
    "            \"triton-v2\",\n",
    "        ],  # label name for the lines\n",
    "        styles=[('blue', '-'), ('green', '-'), ('red', '-'), ('orange', '-')],  # line styles\n",
    "        ylabel=\"ms\",  # label name for the y-axis\n",
    "        plot_name=\"forward\",  # name for the plot. Used also as a file name for saving the plot.\n",
    "        args={'b':1, 'qh':64, 'kh':4, 'd':128, 'vd':128, 'stride':16, 'kernel_size':32, 'select_size': 64, 'top_n':16},  # values for function arguments not in `x_names` and `y_name`\n",
    "    ))\n",
    "def benchmark(b, qh, kh, n, d, vd, stride, kernel_size, select_size, top_n, provider):\n",
    "    device = 'cuda'\n",
    "    dtype = torch.bfloat16\n",
    "    device = 'cuda'\n",
    "    dtype = torch.bfloat16\n",
    "    num_blocks = (n-kernel_size) // stride + 1\n",
    "    q = torch.randn(b, n, qh, d, device=device, dtype=dtype)\n",
    "    k = torch.randn(b, n, kh, d, device=device, dtype=dtype)\n",
    "    v = torch.randn(b, n, kh, vd, device=device, dtype=dtype)\n",
    "    ck = torch.randn(b, num_blocks, kh, d, device=device, dtype=dtype)\n",
    "    lse = torch.rand(b, qh, n, device=device, dtype=torch.float32) + 4\n",
    "    _, fwd_ind, bwd_ind = select_for_fwd_bwd(q, ck, lse, kernel_size, stride, select_size, top_n)\n",
    "    stream = torch.cuda.Stream()\n",
    "    torch.cuda.set_stream(stream)\n",
    "    if provider == 'torch':\n",
    "        if n > 4096:\n",
    "            return 10\n",
    "        ms = triton.testing.do_bench(lambda: torch_select_attn(q, k, v, select_size, fwd_ind))\n",
    "        # ms = triton.testing.do_bench(lambda: select_attn(q, k, v, select_size, ind))\n",
    "    if provider == 'triton-v1':\n",
    "        # return 10\n",
    "        ms = triton.testing.do_bench(lambda: triton_select_attn_v1(q, k, v, select_size, fwd_ind, bwd_ind))\n",
    "    if provider == 'triton-v2':\n",
    "        # return 10\n",
    "        ms = triton.testing.do_bench(lambda: triton_select_attn_v2(q, k, v, select_size, fwd_ind, bwd_ind))\n",
    "    if provider == 'triton-v3':\n",
    "        # return 10\n",
    "        ms = triton.testing.do_bench(lambda: triton_select_attn_v3(q, k, v, select_size, fwd_ind, bwd_ind))\n",
    "    return ms\n",
    "benchmark.run(show_plots=True, print_data=True)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### backward"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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z9q1a7O/GjRoQKdOnbL/rM8udxITE9m5cyfh4eH6mbuEJk2a/Ku1xLZt2yhbtiyg3xP5zu7Zxq7g5MmT1po1a6w1a9ZYgPXGG29Ya9assfbu3WtZlllWV6xYMeu7776z1q1bZ91zzz3nXVZXr149a/ny5dbixYutypUr51hWFxcXZ4WGhlqdO3e2NmzYYM2cOdPy8/P717I6Dw8Pa9y4cdbmzZutoUOHOvWyuieeeMIKDAy0Fi5cmGNJZ3JycvY5PXv2tCIjI6358+dbq1atsqKjo63o6Ojsx88s6bztttustWvXWj///LMVEhJy3iWdzzzzjLV582Zr0qRJ513S6e3tbU2bNs3atGmT1aNHD6tYsWI5Vlg4k0GDBlmLFi2ydu/eba1bt84aNGiQ5XA4rF9++cWyLH1ul+PcVUuWpc/uQgYMGGAtXLjQ2r17t7VkyRKrRYsWVokSJazDhw9blqXP7WJWrFhheXh4WK+++qq1fft269NPP7X8/Pys//73v9nn6PdE/lGQyYUFCxZYwL++unTpYlmWWVr30ksvWaGhoZa3t7d16623Wlu3bs3xGseOHbMefPBBy9/f3woICLAeffRR6+TJkznO+euvv6ymTZta3t7eVunSpa3Ro0f/q5YvvvjCqlKliuXl5WXVqFHDmj17dr5931frfJ8ZYE2dOjX7nFOnTllPPvmkVbx4ccvPz8+69957rYMHD+Z4nT179litW7e2fH19rRIlSlgDBgyw0tPTc5yzYMECq27dupaXl5dVoUKFHO9xxttvv21FRkZaXl5e1vXXX28tW7YsP77tPPGf//zHKlu2rOXl5WWFhIRYt956a3aIsSx9bpfjn0FGn935dejQwQoPD7e8vLys0qVLWx06dMjRB0Wf28X98MMPVs2aNS1vb28rKirKeu+993I8rt8T+cdhWZZlz7UgERERkaujOTIiIiLishRkRERExGUpyIiIiIjLUpARERERl6UgIyIiIi5LQUZERERcloKMiIiIuCwFGREREXFZCjIiIiLishRkRERExGUpyIiIiIjL8rC7ABGRy9W8eXNq166Nj48PH3zwAV5eXvTs2ZNhw4bZXZqIXGO6IiMiLmn69OkUKVKE5cuXM3bsWIYPH86vv/5qd1kico1p92sRcTnNmzcnMzOT33//PfvY9ddfzy233MLo0aNtrExErjVdkRERl1S7du0c4/DwcA4fPmxTNSJiFwUZEXFJnp6eOcYOh4OsrCybqhERuyjIiIiIiMtSkBERERGXpSAjIiIiLkurlkRERMRl6YqMiIiIuCwFGREREXFZCjIiIiLishRkRERExGUpyIiIiIjLUpARERERl6UgIyIiIi5LQUZERERcloKMiIiIuCwFGREREXFZCjIiIiLisv4PcZ7q76Lt5VIAAAAASUVORK5CYII=",
      "text/plain": [
       "<Figure size 640x480 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "forward:\n",
      "         n  triton-v1  torch  triton-v3  triton-v2\n",
      "0   8192.0   5.547436   10.0   4.999887  11.269884\n",
      "1  16384.0  10.607917   10.0  10.368139  19.888527\n",
      "2  24576.0  16.205456   10.0  15.833734  30.186966\n",
      "3  32768.0  22.001801   10.0  21.624271  35.729713\n",
      "4  40960.0  28.110037   10.0  27.348577  42.742847\n",
      "5  49152.0  34.417793   10.0  33.358147  50.118591\n",
      "6  57344.0  40.619217   10.0  39.057457  59.812576\n",
      "7  65536.0  48.890701   10.0  45.623886  65.544701\n"
     ]
    }
   ],
   "source": [
    "#bwd_ind会被原地修改,得制止下\n",
    "torch.cuda.empty_cache()\n",
    "@triton.testing.perf_report(\n",
    "    triton.testing.Benchmark(\n",
    "        x_names=['n'],  # argument names to use as an x-axis for the plot\n",
    "        x_vals=[8192 * i for i in range(1, 8+1)],  # different possible values for `x_name`\n",
    "        line_arg='provider',  # argument name whose value corresponds to a different line in the plot\n",
    "        line_vals=['triton-v1', 'torch', 'triton-v3', 'triton-v2'],  # possible values for `line_arg``\n",
    "        line_names=[\n",
    "            \"triton-v1\",\n",
    "            \"torch\",\n",
    "            \"triton-v3\",\n",
    "            \"triton-v2\",\n",
    "        ],  # label name for the lines\n",
    "        styles=[('blue', '-'), ('green', '-'), ('red', '-'), ('orange', '-')],  # line styles\n",
    "        ylabel=\"ms\",  # label name for the y-axis\n",
    "        plot_name=\"forward\",  # name for the plot. Used also as a file name for saving the plot.\n",
    "        args={'b':1, 'qh':64, 'kh':4, 'd':128, 'vd':128, 'stride':16, 'kernel_size':32, 'select_size': 64, 'top_n':16},  # values for function arguments not in `x_names` and `y_name`\n",
    "    ))\n",
    "def benchmark(b, qh, kh, n, d, vd, stride, kernel_size, select_size, top_n, provider):\n",
    "    device = 'cuda'\n",
    "    dtype = torch.bfloat16\n",
    "    device = 'cuda'\n",
    "    dtype = torch.bfloat16\n",
    "    num_blocks = (n-kernel_size) // stride + 1\n",
    "    q = torch.randn(b, n, qh, d, device=device, dtype=dtype)\n",
    "    k = torch.randn(b, n, kh, d, device=device, dtype=dtype)\n",
    "    v = torch.randn(b, n, kh, vd, device=device, dtype=dtype)\n",
    "    q.requires_grad_(True)\n",
    "    k.requires_grad_(True)\n",
    "    v.requires_grad_(True)\n",
    "    ck = torch.randn(b, num_blocks, kh, d, device=device, dtype=dtype)\n",
    "    lse = torch.rand(b, qh, n, device=device, dtype=torch.float32) + 10\n",
    "    _, fwd_ind, bwd_ind = select_for_fwd_bwd(q, ck, lse, kernel_size, stride, select_size, top_n)\n",
    "    stream = torch.cuda.Stream()\n",
    "    torch.cuda.set_stream(stream)\n",
    "    if provider == 'torch':\n",
    "        if n>4096:\n",
    "            return 10\n",
    "        y = torch_select_attn(q, k, v, select_size, fwd_ind.long())\n",
    "        dy = torch.rand_like(y)\n",
    "        ms = triton.testing.do_bench(lambda: y.backward(dy, retain_graph=True), grad_to_none=[q, k, v])\n",
    "    if provider == 'triton-v1':\n",
    "        y = triton_select_attn_v1(q, k, v, select_size, fwd_ind, bwd_ind, inplace=False)\n",
    "        dy = torch.rand_like(y)\n",
    "        ms = triton.testing.do_bench(lambda: y.backward(dy, retain_graph=True), grad_to_none=[q, k, v])\n",
    "    if provider == 'triton-v2':\n",
    "        y = triton_select_attn_v2(q, k, v, select_size, fwd_ind, bwd_ind, inplace=False)\n",
    "        dy = torch.rand_like(y)\n",
    "        ms = triton.testing.do_bench(lambda: y.backward(dy, retain_graph=True), grad_to_none=[q, k, v])\n",
    "    if provider == 'triton-v3':\n",
    "        y = triton_select_attn_v3(q, k, v, select_size, fwd_ind, bwd_ind, inplace=False)\n",
    "        dy = torch.rand_like(y)\n",
    "        ms = triton.testing.do_bench(lambda: y.backward(dy, retain_graph=True), grad_to_none=[q, k, v])\n",
    "    return ms\n",
    "benchmark.run(show_plots=True, print_data=True)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Combine"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "import torch\n",
    "import triton\n",
    "import triton.language as tl\n",
    "import math\n",
    "from copy import deepcopy\n",
    "import os\n",
    "os.environ['TRITON_PRINT_AUTOTUNING'] = '1'\n",
    "from combine import fused_sigmoid_combine\n",
    "from torch_code import sigmoid_combine"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [],
   "source": [
    "seed = 11\n",
    "torch.cuda.manual_seed(seed)\n",
    "torch.manual_seed(seed)\n",
    "device = 'cuda'\n",
    "dtype = torch.bfloat16\n",
    "b, n, h, d = 1, 8192 * 8, 64, 128\n",
    "a1 = torch.randn(b, n, h, d, device=device, dtype=dtype)\n",
    "b1 = torch.randn(b, n, h, d, device=device, dtype=dtype)\n",
    "c1 = torch.randn(b, n, h, d, device=device, dtype=dtype)\n",
    "w1 = torch.randn(b, n, h, 3, device=device, dtype=dtype)\n",
    "a1.requires_grad_(True)\n",
    "b1.requires_grad_(True)\n",
    "c1.requires_grad_(True)\n",
    "w1.requires_grad_(True)\n",
    "a2 = deepcopy(a1)\n",
    "b2 = deepcopy(b1)\n",
    "c2 = deepcopy(c1)\n",
    "w2 = deepcopy(w1)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "True\n",
      "True\n",
      "True\n",
      "True\n",
      "True\n"
     ]
    }
   ],
   "source": [
    "y1 = fused_sigmoid_combine(a1, b1, c1, w1)\n",
    "y2 = sigmoid_combine(a2, b2, c2, w2)\n",
    "dy = torch.randn_like(y1)\n",
    "y1.backward(dy)\n",
    "y2.backward(dy)\n",
    "print(torch.allclose(y1, y2, 5e-2, 5e-2))\n",
    "print(torch.allclose(a1.grad, a2.grad, 5e-2, 5e-2))\n",
    "print(torch.allclose(b1.grad, b2.grad, 5e-2, 5e-2))\n",
    "print(torch.allclose(c1.grad, c2.grad, 5e-2, 5e-2))\n",
    "print(torch.allclose(w1.grad, w2.grad, 1e-1, 1e-1))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1.219897985458374\n",
      "5.314684867858887\n"
     ]
    }
   ],
   "source": [
    "print(triton.testing.do_bench(lambda:fused_sigmoid_combine(a1, b1, c1, w1)))\n",
    "print(triton.testing.do_bench(lambda:sigmoid_combine(a2, b2, c2, w2)))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# NSA_attn\n",
    "- 效果还不是最好，目前知识demo"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [],
   "source": [
    "import torch\n",
    "import triton\n",
    "import triton.language as tl\n",
    "import math\n",
    "from copy import deepcopy\n",
    "import os\n",
    "os.environ['TRITON_PRINT_AUTOTUNING'] = '1'\n",
    "\n",
    "try:\n",
    "    from flash_attn import flash_attn_func as fa2\n",
    "    HAVE_FA2 = True\n",
    "except:\n",
    "    fa2 = None\n",
    "    HAVE_FA2 = False\n",
    "\n",
    "try:\n",
    "    from flash_attn_interface import flash_attn_func as fa3\n",
    "    HAVE_FA3 = True\n",
    "except:\n",
    "    fa3 = None\n",
    "    HAVE_FA3 = False\n",
    "\n",
    "\n",
    "from triton_flash_attn2 import triton_fa2\n",
    "from nsa_attn import NsaAttention"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAjsAAAGwCAYAAABPSaTdAAAAOnRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjEwLjAsIGh0dHBzOi8vbWF0cGxvdGxpYi5vcmcvlHJYcgAAAAlwSFlzAAAPYQAAD2EBqD+naQAAfMVJREFUeJzt3Xd8Tfcfx/HXzd6JkEkSMWqvmrFqxCqKUqN2VaulrepQrdZoS6v9dSsdtqK22iM2MUvtHYLIsLL3Pb8/jty4BEGSc3PzeT4e98EZufdzL5K37/me70enKIqCEEIIIYSZstC6ACGEEEKI/CRhRwghhBBmTcKOEEIIIcyahB0hhBBCmDUJO0IIIYQwaxJ2hBBCCGHWJOwIIYQQwqxZaV2AKdDr9URERODs7IxOp9O6HCGEEELkgqIoxMfH4+vri4XFg8dvJOwAERER+Pn5aV2GEEIIIZ7A5cuXKVWq1AOPS9gBnJ2dAfXDcnFx0bgaIYQQQuRGXFwcfn5+hp/jDyJhBwyXrlxcXCTsCCGEEIXMo6agyARlIYQQQpg1CTtCCCGEMGsSdoQQQghh1mTOTi7p9XrS0tK0LkPkERsbm4fepiiEEMJ8aBp2pkyZwpQpU7h48SIAVapU4bPPPqNdu3YApKSk8N5777FgwQJSU1Np06YNv/76K15eXobnCA8P54033mDLli04OTnRv39/Jk6ciJVV3r21tLQ0wsLC0Ov1efacQlsWFhYEBgZiY2OjdSlCCCHymaZhp1SpUnz11VeUL18eRVGYNWsWnTp14tChQ1SpUoV3332X1atXs2jRIlxdXRk2bBgvvvgiu3btAiAzM5P27dvj7e3N7t27uXbtGv369cPa2poJEybkSY2KonDt2jUsLS3x8/OT0QAzkLWI5LVr1/D395eFJIUQwszpFEVRtC7ibu7u7nzzzTd069YNDw8P5s2bR7du3QA4deoUlSpVIjQ0lAYNGrB27Vo6dOhARESEYbRn6tSpjBw5kpiYmFz/rz0uLg5XV1diY2Pvu/U8PT2dc+fO4evri6ura96+WaGZ2NhYIiIiKFeuHNbW1lqXI4QQ4gk87Of33UxmmCIzM5MFCxaQmJhIUFAQBw8eJD09neDgYMM5FStWxN/fn9DQUABCQ0OpVq2a0WWtNm3aEBcXx/Hjxx/4WqmpqcTFxRk9HlYXIJc7zEzWn2fWn68QQgjzpXnYOXr0KE5OTtja2jJkyBCWLVtG5cqViYyMxMbGBjc3N6Pzvby8iIyMBCAyMtIo6GQdzzr2IBMnTsTV1dXwyE2rCLnUYV7kz1MIIYoOzcNOhQoVOHz4MHv37uWNN96gf//+nDhxIl9fc9SoUcTGxhoely9fztfXE0IIIYR2NL/13MbGhnLlygFQu3Zt9u/fz48//kiPHj1IS0vj9u3bRqM7UVFReHt7A+Dt7c2+ffuMni8qKspw7EFsbW2xtbXN43cihBBCCFOk+cjOvfR6PampqdSuXRtra2tCQkIMx06fPk14eDhBQUEABAUFcfToUaKjow3nbNy4ERcXFypXrlzgtQshhBDC9GgadkaNGsX27du5ePEiR48eZdSoUWzdupXevXvj6urKoEGDGDFiBFu2bOHgwYMMHDiQoKAgGjRoAEDr1q2pXLkyffv25b///mP9+vWMHj2aoUOHFvmRmwEDBqDT6fjqq6+M9i9fvtxovsoff/xBjRo1cHJyws3NjVq1ajFx4sQcn7NixYrY2to+dD6UEEIIcbfLsZf599q/mtagadiJjo6mX79+VKhQgZYtW7J//37Wr19Pq1atAPj+++/p0KEDXbt2pWnTpnh7e7N06VLD11taWrJq1SosLS0JCgqiT58+9OvXj/Hjx2v1lkyKnZ0dX3/9Nbdu3crx+PTp0xk+fDhvv/02hw8fZteuXXz44YckJCTcd+7OnTtJTk6mW7duzJo1K79LF0IIYQaiEqIInhNM81nN2XNlj2Z1mNw6O1p42H36KSkphIWFERgYiJ2dHYoCSUna1OngALm9iWjAgAHcuHGDc+fO0bFjRyZNmgSoIztdunRBURQ6d+5MsWLFmDFjxiOfb+DAgXh7e/Pcc8/xzjvvcPr06ad5K5q7989VCCFE3rqZfJPms5pzJOoI/q7+7Bi4A39X/zx9jdyus6P5BOXCJikJnJy0ee2EBHB0zP35lpaWTJgwgZdffpm3336bUqVKGR339vZm27ZtXLp0iYCAgAc+T3x8PIsWLWLv3r1UrFiR2NhYduzYQZMmTZ70rQghhDBj8anxtPurHUeijuDt5M2mvpvyPOg8DpOboCzyVpcuXahZsyZjxoy579iYMWNwc3OjdOnSVKhQgQEDBrBw4cL7eoAtWLCA8uXLU6VKFSwtLenZsyfTpk0rqLcghBCiEElKT6Lj/I7su7oPd3t3NvbdSPni5TWtScLOY3JwUEdYtHg4ODxZzV9//TWzZs3i5MmTRvt9fHwIDQ3l6NGjvPPOO2RkZNC/f3/atm1rFHimT59Onz59DNt9+vRh0aJFxMfHP1lBQgghzFJaZhrdFnZj26VtuNi6sKHPBqp6VtW6LJmzA483Z6ewGDBgALdv32b58uUAtG/fHmtrawYMGGCYs5OTnTt30qRJEzZv3kzz5s05ceIEVapUwcLCwugurszMTH7//XcGDx5cEG8nzxXWP1chhDBVGfoMei7uyZKTS7C3smdD3w009m+cr68pc3aEka+++oqaNWtSoUKFh56XtT5RYmIiANOmTaNp06ZMnjzZ6LwZM2Ywbdq0Qht2hBBC5B29oueVFa+w5OQSbCxtWNFzRb4HncchYaeIqFatGr179+ann34y7HvjjTfw9fWlRYsWlCpVimvXrvHFF1/g4eFBUFAQ6enpzJkzh/Hjx1O1qvEw5Kuvvsp3333H8ePHqVKlSkG/HSGEECZCURSGrRnGnCNzsNRZsrDbQlqVbaV1WUZkzk4RMn78eKO5OMHBwezZs4eXXnqJZ555hq5du2JnZ0dISAjFixfnn3/+4caNG3Tp0uW+56pUqRKVKlWSicpCCFGEKYrCyE0jmXJgCjp0zOkyh04VO2ld1n1kzg7mOWdHPJz8uQohxNP7fNvnfLb1MwB+7/A7g2sX7NSG3M7ZkZEdIYQQQjy270O/NwSd79t8X+BB53FI2BFCCCHEY/nj4B+M2DACgPHNxjO8wXBtC3oECTtCCCGEyLV5R+fx+qrXAfiw4YeMbjpa44oeTcKOEEIIIXJlxakV9FvWDwWFN+u8yVfBXxmtwWaqJOwIIYQQ4pE2nt9I98XdyVQy6VejHz8//3OhCDogYUcIIYQQj7Dj0g46LehEWmYaXSt1ZdoL07DQFZ4IUXgqFUIIIUSBOxBxgPbz2pOckUy7cu2Y13UeVhaFa01iCTtCCCGEyNGx6GO0mduG+LR4ngt4jiXd1XYQhY2EHQHA2LFjqVmzptZlCCGEMBFnb5yl1ZxW3Ey+Sf2S9VnZayX21vZal/VEJOyYIZ1O99DH2LFj7/ua999/n5CQEMP2gAED6Ny5c4HVXLp06fvqLFWqlNE5bdq0wdLSkv3799/39RMnTqRu3bo4Ozvj6elJ586dOX36dEGVL4QQZiU8NpyWs1sSmRBJda/qrO29FmdbZ63LemISdszQtWvXDI8ffvgBFxcXo33vv/++4VxFUcjIyMDJyYnixYtrWLXau+vuOg8dOmQ4Fh4ezu7duxk2bBjTp0+/72u3bdvG0KFD2bNnDxs3biQ9PZ3WrVsburcLIYTInciESFrObsnluMtUKF6BDX02UMy+mNZlPRUJO2bI29vb8HB1dUWn0xm2T506hbOzM2vXrqV27drY2tqyc+dOo8tYY8eOZdasWaxYscIwyrJ161YAjh49SosWLbC3t6d48eK89tprJCQkGF47a0To22+/xcfHh+LFizN06FDS09MfWbezs7NR7R4eHoZjM2bMoEOHDrzxxhvMnz+f5ORko69dt24dAwYMoEqVKtSoUYOZM2cSHh7OwYMHn/4DFUKIIuJG0g1azWnFuZvnKO1Wmk39NuHl5KV1WU+tcE2nNgGKopCUnqTJaztYO+TZmgYfffQR3377LWXKlKFYsWKGMAPqJa2TJ08SFxfHjBkzAHB3dycxMZE2bdoQFBTE/v37iY6O5tVXX2XYsGHMnDnT8PVbtmzBx8eHLVu2cO7cOXr06EHNmjUZPPjJ+qYoisKMGTOYPHkyFStWpFy5cixevJi+ffs+8GtiY2MNdQshhHi0uNQ42v7VlmPRx/Bx8mFT302Ucin16C8sBCTsPKak9CScJjpp8toJoxJwtHHMk+caP348rVq1yvGYk5MT9vb2pKam4u3tbdg/a9YsUlJSmD17No6Oah2//PILHTt25Ouvv8bLS03/xYoV45dffsHS0pKKFSvSvn17QkJCHhl2Ro4cyejR2cuOT5gwgbfffptNmzaRlJREmzZtAOjTpw/Tpk17YNjR6/UMHz6cRo0aUbVq1dx/KEIIUUQlpiXSfl57DkQcoIRDCTb120RZ97Jal5Vn5DJWEVWnTp3H/pqTJ09So0YNQ9ABaNSoEXq93mgycJUqVbC0tDRs+/j4EB0dDagBxsnJyfAIDw83nPfBBx9w+PBhw6Nfv34ATJ8+nR49emBlpWbzXr16sWvXLs6fP59jnUOHDuXYsWMsWLDgsd+jEEIUNakZqXT5uws7w3fiauvKhj4bqOxRWeuy8pSM7DwmB2sHEkYlPPrEfHrtvHJ3YMlr1tbWRts6nQ69Xg/AkCFD6N69u+GYr6+v4fclSpSgXLlyRl978+ZNli1bRnp6OlOmTDHsz8zMZPr06Xz55ZdG5w8bNoxVq1axffv2++7mEkIIYSw9M52eS3qy8cJGHK0dWdN7DbV8amldVp6TsPOYdDpdnl1KMmU2NjZkZmYa7atUqRIzZ84kMTHREJZ27dqFhYUFFSpUyNXzuru7P9Y8mr/++otSpUqxfPlyo/0bNmzgf//7H+PHj8fS0hJFUXjrrbdYtmwZW7duJTAwMNevIYQQRVGmPpMBKwaw/NRybC1tWdFzBQ39GmpdVr6Qy1giR6VLl+bIkSOcPn2a69evk56eTu/evbGzs6N///4cO3aMLVu28NZbb9G3b1/DfJ28Nm3aNLp160bVqlWNHoMGDeL69eusW7cOUC9dzZ07l3nz5uHs7ExkZCSRkZH33bUlhBBCvfHjjdVvMO+o2vphcffFtCzTUuuy8o2EHZGjwYMHU6FCBerUqYOHhwe7du3CwcGB9evXc/PmTerWrUu3bt1o2bIlv/zyS77UcPDgQf777z+6du163zFXV1datmzJtGnTAJgyZQqxsbE0a9YMHx8fw+Pvv//Ol9qEEKKwUhSF9ze8zx///oGFzoK5XebS4ZkOWpeVr3SKoihaF6G1uLg4XF1diY2NxcXFxehYSkoKYWFhBAYGYmdnp1GFIq/Jn6sQoqgau3Us47aNA2DaC9N4pdYrGlf05B728/tuMrIjhBBCFBHf7v7WEHR+avtToQ46j0PCjhBCCFEETNk/hQ82fgDAhBYTeKv+WxpXVHAk7AghhBBmbs5/c3hzzZsAjGo8ilFNRmlcUcGSsCOEEEKYsaUnlzJgxQAA3qr3Fl+2+PLhX2CGJOwIIYQQZmrduXX0XNwTvaJnYM2B/ND2hzzrsViYSNgRQgghzNC2i9vo8ncX0vXpdK/SnT86qreaF0VF810LIYQQZmzf1X10mN+BlIwU2pdvz5wuc7C0sHz0F5opCTtCCCGEGTkSdYS2c9uSkJZAi8AWLHppETaWNlqXpSkJO0IIIYSZOH39NK3mtOJWyi2CSgWxoucK7K3ttS5LcxJ2hBBCCDNw8fZFgucEE50YTU3vmqzpvQYnGyetyzIJEnbM1IABA9DpdPc9zp07B8DEiROxtLTkm2++ue9rly5dSqtWrfDw8MDFxYWgoCDWr19f0G9BCCFELkXER9BydkuuxF2hUolKbOizATc7N63LMhkSdsxY27ZtuXbtmtEjMDAQgOnTp/Phhx8yffr0+75u+/bttGrVijVr1nDw4EGaN29Ox44dOXToUEG/BSGEEI9wPek6rea04sKtCwS6BbKx70Y8HD20LsukWGldgMg/tra2eHt737d/27ZtJCcnM378eGbPns3u3btp2LCh4fgPP/xgdP6ECRNYsWIFK1eupFatWvldthBCiFy6nXKb1nNacyLmBCWdSxLSL4SSLiW1LsvkSNh5XIoCSUnavLaDA+TBYlDTpk2jV69eWFtb06tXL6ZNm2YUdu6l1+uJj4/H3d39qV9bCCFE3khMS6T9vPYcijyEh4MHm/ptIrBYoNZlmSQJO48rKQmcNJrwlZAAjo65Pn3VqlU43VVru3btmDZtGosXLyY0NBSAPn360KRJE3788Uejc+/27bffkpCQQPfu3Z+ufiGEEHkiJSOFTgs6sfvybtzs3NjYdyMVS1TUuiyTJWHHjDVv3pwpU6YYth0dHZk/fz5ly5alRo0aANSsWZOAgAD+/vtvBg0adN9zzJs3j3HjxrFixQo8PT0LrHYhhBA5S89Mp/ui7oSEheBk48Ta3mup4V1D67JMmoSdx+XgoI6waPXaj8HR0ZFy5coZ7Zs2bRrHjx/Hyir7j16v1zN9+vT7ws6CBQt49dVXWbRoEcHBwU9etxBCiDyRqc+k77K+rDyzEjsrO1b2WkmDUg20LsvkSdh5XDrdY11KMiVHjx7lwIEDbN261Wj+zc2bN2nWrBmnTp2iYkV1GHT+/Pm88sorLFiwgPbt22tVshBCiDv0ip7XVr7G38f/xtrCmiXdl9CsdDOtyyoUNL31fOLEidStWxdnZ2c8PT3p3Lkzp0+fNjqnWbNm960VM2TIEKNzwsPDad++PQ4ODnh6evLBBx+QkZFRkG+lUJg2bRr16tWjadOmVK1a1fBo2rQpdevWZdq0aYB66apfv37873//o379+kRGRhIZGUlsbKzG70AIIYomRVF4d927TD88HQudBfO7zuf58s9rXVahoWnY2bZtG0OHDmXPnj1s3LiR9PR0WrduTWJiotF5gwcPNlorZtKkSYZjmZmZtG/fnrS0NHbv3s2sWbOYOXMmn332WUG/HZOWlpbG3Llz6dq1a47Hu3btyuzZs0lPT+f3338nIyODoUOH4uPjY3i88847BVy1EEIIgE+3fMpP+34CYPoL0+laOefv5SJnOkVRFK2LyBITE4Onpyfbtm2jadOmgDqyU7NmzfvWfsmydu1aOnToQEREBF5eXgBMnTqVkSNHEhMTg43No5ufxcXF4erqSmxsLC4uLkbHUlJSCAsLIzAwEDs7u6d7g8JkyJ+rEKKw+GrnV4wKGQXA5Ocn82bdNzWuyHQ87Of33UxqBeWsyyT3rufy119/UaJECapWrcqoUaNIumudm9DQUKpVq2YIOgBt2rQhLi6O48eP5/g6qampxMXFGT2EEEIIU/PLvl8MQefr4K8l6Dwhk5mgrNfrGT58OI0aNaJq1aqG/S+//DIBAQH4+vpy5MgRRo4cyenTp1m6dCkAkZGRRkEHMGxHRkbm+FoTJ05k3Lhx+fROhBBCiKc38/BM3lr7FgCjm4zmw0YfalxR4WUyYWfo0KEcO3aMnTt3Gu1/7bXXDL+vVq0aPj4+tGzZkvPnz1O2bNkneq1Ro0YxYsQIw3ZcXBx+fn5PVrgQQgiRxxYdX8Sgf9TlQIbXH8745uM1rqhwM4nLWMOGDWPVqlVs2bKFUqVKPfTc+vXrAxi6d3t7exMVFWV0TtZ2Tn2hQO0Z5eLiYvQQQgghTMHqM6t5eenL6BU9r9Z6le/afIcuD1oFFWWahh1FURg2bBjLli1j8+bNho7cD3P48GEAfHx8AAgKCuLo0aNER0cbztm4cSMuLi5Urlw5X+oWQggh8sPmsM10XdiVDH0Gvar2YmqHqRJ08oCml7GGDh3KvHnzWLFiBc7OzoY5Nq6urtjb23P+/HnmzZvH888/T/HixTly5AjvvvsuTZs2pXr16gC0bt2aypUr07dvXyZNmkRkZCSjR49m6NCh2Nraavn2hBBCiFwLvRzKC/NfIDUzlU4VOjGr8ywsLSy1LsssaDqyM2XKFGJjY2nWrJnRei5///03ADY2NmzatInWrVtTsWJF3nvvPbp27crKlSsNz2FpacmqVauwtLQkKCiIPn360K9fP8aPl+ubQgghCofDkYdp91c7EtMTCS4TzIJuC7C2tNa6LLOh6cjOo5b48fPzY9u2bY98noCAANasWZNXZQkhhBAF5mTMSVrPaU1saiyN/BqxvMdy7Kxk/a+8ZBITlIUQQoii6MKtCwTPCSYmKYbaPrVZ/fJqHG0KZ/9FUyZhRwghhNDAlbgrBM8OJiI+gsoelVnXZx2udq5al2WWJOyYqQEDBtzXQFWn0xlu2Z84cSKWlpZ88803933tzp07adSoEcWLF8fe3p6KFSvy/fffF/RbEEIIsxWdGE3w7GDCbodRtlhZNvXdRAmHElqXZbZMZlFBkffatm3LjBkzjPZ5eHgAMH36dD788EOmT5/OBx98YHSOo6Mjw4YNo3r16jg6OrJz505ef/11HB0djRZ5FEII8fhuJd+i9ZzWnL5xGj8XP0L6heDj7KN1WWZNRnbMmK2tLd7e3kYPS0tLtm3bRnJyMuPHjycuLo7du3cbfV2tWrXo1asXVapUoXTp0vTp04c2bdqwY8cOjd6JEEKYh/jUeJ6f9zz/Rf2Hl6MXm/ptIsAtQOuyzJ6M7DwuRYHMpEeflx8sHSAPFpeaNm0avXr1wtraml69ejFt2jQaNmz4wPMPHTrE7t27+eKLL576tYUQoqhKTk/mhQUvsOfKHorZFWNj3408U/wZrcsqEiTsPK7MJFjopM1rd08Aq9zP0l+1ahVOTtm1tmvXjmnTprF48WJCQ0MB6NOnD02aNOHHH380OhegVKlSxMTEkJGRwdixY3n11Vfz5n0IIUQRk5aZRrdF3dh6cSvONs6s77Oeal7VtC6ryJCwY8aaN2/OlClTDNuOjo7Mnz+fsmXLUqNGDQBq1qxJQEAAf//9N4MGDTL6+h07dpCQkMCePXv46KOPKFeuHL169SrQ9yCEEIVdhj6DPkv7sObsGuyt7Fn18irqlqyrdVlFioSdx2XpoI6waPXaj8HR0ZFy5coZ7Zs2bRrHjx/Hyir7j16v1zN9+vT7wk5Wr7Jq1aoRFRXF2LFjJewIIcRj0Ct6Xv3nVRadWISNpQ3LeiyjaUBTrcsqciTsPC6d7rEuJZmSo0ePcuDAAbZu3Yq7u7th/82bN2nWrBmnTp2iYsWKOX6tXq8nNTW1oEoVQohCT1EU3l77NrP+m4WlzpIFXRfQplwbrcsqkiTsFCHTpk2jXr16NG16//8q6taty7Rp0/jmm2+YPHky/v7+huCzfft2vv32W95+++2CLlkIIQolRVEYFTKKyfsno0PHzM4z6VKpi9ZlFVly63kRkZaWxty5c+natWuOx7t27crs2bNJT09Hr9czatQoatasSZ06dZg8eTJff/21NFcVQohcmrBjAl/v+hqAqR2m0qd6H40rKtp0yqO6cRYBcXFxuLq6Ehsbi4uLi9GxlJQUwsLCCAwMxM5OGrOZC/lzFULklx/3/Mjw9cMB+LbVt7zX8D1tCzJjD/v5fTcZ2RFCCCHyyLR/pxmCztjnxkrQMRESdoQQQog8sODYAgavHAzAe0Hv8dlzn2lckcgiYUcIIYR4Sv+c/oe+y/qioDCk9hC+afUNujxY8V7kDQk7QgghxFPYdGETLy16SV08sHofJrefLEHHxEjYySWZx21e5M9TCJEXdoXvotOCTqRlptGlYhdmdJqBhU5+tJoa+RN5BEtLS0C9dVuYj6w/z6w/XyGEeFwHIw7y/LznSUpPok3ZNszvOh8rC1m+zhTJn8ojWFlZ4eDgQExMDNbW1lhYSD4s7PR6PTExMTg4OBi1zRBCiNw6Hn2cNnPbEJcaR9OApiztsRRbK1utyxIPIN/pH0Gn0+Hj40NYWBiXLl3SuhyRRywsLPD395fr6kKIx3bu5jlazWnFjeQb1PWty8peK3GwfrzehaJgSdjJBRsbG8qXLy+XssyIjY2NjNIJIR7b5djLtJzdkmsJ16jmWY11fdbhYvvgxeyEaZCwk0sWFhay0q4QQhRhUQlRBM8JJjw2nPLu5dnYdyPu9u6P/kKhOfmvrRBCCPEIN5Nv0mpOK87cOEOAawAh/ULwcvLSuiyRSxJ2hBBCiIeIS42j7dy2HI0+ireTN5v6bcLP1U/rssRjkLAjhBBCPEBSehId53dkf8R+itsXZ1PfTZRzL6d1WeIxSdgRQgghcpCakcqLf7/I9kvbcbF1YX2f9VTxrKJ1WeIJSNgRQggh7pGhz6DXkl6sP78eB2sH1ry8htq+tbUuSzwhCTtCCCHEXfSKnoErBrLs1DJsLG1Y0XMFjfwbaV2WeAoSdoQQQog7FEVh6OqhzD0yF0udJYteWkRwmWCtyxJPScKOEEIIgRp0Ptj4AVMPTkWHjjld5vBChRe0LkvkAQk7QgghBDB+23j+F/o/AP7o+Ae9qvXSuCKRVyTsCCGEKPK+C/2OsdvGAvBDmx8Y9OwgbQsSeUrCjhBCiCLt94O/896G9wD4vPnnvNPgHY0rEnlNwo4QQogia+6RuQxZNQSAkY1G8kmTTzSuSOQHCTtCCCGKpGUnlzFg+QAUFIbWHcrElhPR6XRalyXygYQdIYQQRc76c+vpuaQnmUom/Wv056d2P0nQMWMSdoQQQhQp2y9tp8vfXUjLTKNb5W78+cKfWOjkx6E5kz9dIYQQRcb+q/vpMK8DyRnJPF/+ef568S+sLKy0LkvkMwk7QgghioSjUUdpM7cN8WnxNCvdjMUvLcbG0kbrskQBkLAjhBDC7J25cYZWc1pxK+UW9UvW55+e/2Bvba91WaKASNgRQghh1i7dvkTw7GCiEqOo4VWDtb3X4mzrrHVZogBJ2BFCCGG2rsVfo+XsllyOu0yF4hXY0HcDxeyLaV2WKGASdoQQQpil60nXaTWnFedvnae0W2k29duEp6On1mUJDUjYEUIIYXZiU2JpO7ctx2OO4+vsS0i/EEq5lNK6LKERCTtCCCHMSmJaIu3ntefgtYOUcCjBpr6bKFOsjNZlCQ1pGnYmTpxI3bp1cXZ2xtPTk86dO3P69Gmjc1JSUhg6dCjFixfHycmJrl27EhUVZXROeHg47du3x8HBAU9PTz744AMyMjIK8q0IIYQwASkZKXT5uwu7Lu/C1daVDX02UMmjktZlCY1pGna2bdvG0KFD2bNnDxs3biQ9PZ3WrVuTmJhoOOfdd99l5cqVLFq0iG3bthEREcGLL75oOJ6ZmUn79u1JS0tj9+7dzJo1i5kzZ/LZZ59p8ZaEEEJoJD0znR6Le7DxwkYcrR1Z23sttXxqaV2WMAE6RVEUrYvIEhMTg6enJ9u2baNp06bExsbi4eHBvHnz6NatGwCnTp2iUqVKhIaG0qBBA9auXUuHDh2IiIjAy8sLgKlTpzJy5EhiYmKwsXn0glFxcXG4uroSGxuLi4tLvr5HIYQQeS9Tn0nfZX2Zf2w+tpa2rOm9hhaBLbQuS+Sz3P78Nqk5O7GxsQC4u7sDcPDgQdLT0wkODjacU7FiRfz9/QkNDQUgNDSUatWqGYIOQJs2bYiLi+P48eM5vk5qaipxcXFGDyGEEIWToigMWTWE+cfmY2VhxZLuSyToCCMmE3b0ej3Dhw+nUaNGVK1aFYDIyEhsbGxwc3MzOtfLy4vIyEjDOXcHnazjWcdyMnHiRFxdXQ0PPz+/PH43QgghCoKiKIxYP4I/D6nNPP968S/aP9Ne67KEiTGZsDN06FCOHTvGggUL8v21Ro0aRWxsrOFx+fLlfH9NIYQQeW/M1jH8sPcHAKa9MI3uVbprW5AwSSbR6nXYsGGsWrWK7du3U6pU9joI3t7epKWlcfv2baPRnaioKLy9vQ3n7Nu3z+j5su7WyjrnXra2ttja2ubxuxBCCFGQJu2axOfbPwfg53Y/M6DmAG0LEiZL05EdRVEYNmwYy5YtY/PmzQQGBhodr127NtbW1oSEhBj2nT59mvDwcIKCggAICgri6NGjREdHG87ZuHEjLi4uVK5cuWDeiBBCiAL16/5fGblpJAATW05kWL1hGlckTJmmIztDhw5l3rx5rFixAmdnZ8McG1dXV+zt7XF1dWXQoEGMGDECd3d3XFxceOuttwgKCqJBgwYAtG7dmsqVK9O3b18mTZpEZGQko0ePZujQoTJ6I4QQZmjW4VkMXTMUgI8bf8xHjT/SuCJh6jS99Vyn0+W4f8aMGQwYMABQFxV87733mD9/PqmpqbRp04Zff/3V6BLVpUuXeOONN9i6dSuOjo7079+fr776Ciur3GU5ufVcCCEKh8UnFtNjcQ/0ip63673ND21/eODPEmH+cvvz26TW2dGKhB0hhDB9a86uofOCzqTr03ml5iv88cIfWOhM5j4boYFCuc6OEEIIkZOtF7fSdWFX0vXp9KjSg987/i5BR+Sa/E0RQghh0vZe2UvH+R1JyUih4zMdmdNlDpYWllqXJXIrMRF279a0BAk7QgghTNZ/kf/R9q+2JKQl0DKwJQtfWoi1pbXWZYnc2r0bataEtm3h0iXNypCwI4QQwiSdun6KVnNacTvlNg39GrK853LsrOy0LkvkRmoqjBwJTZrAuXPg6goP6GpQEExiUUEhhBDibmG3wgieHUxMUgy1vGux+uXVONk4aV2WyI1Dh6BfPzh2TN3u3x9++AHuaf1UkGRkRwghhEm5GneV4DnBXI2/SqUSlVjfZz1udm5alyUeJSMDPv8c6tVTg46nJyxbBjNnahp0QEZ2hBBCmJCYxBiC5wRz4dYFyhQrw6Z+m/Bw9NC6LPEoJ0+qIzj796vbL74IU6eCh2n82cnIjhBCCJNwO+U2ree25tT1U5RyKUVIvxB8nX21Lks8jF4P338Pzz6rBh03N5g7FxYvNpmgAzKyI4QQwgQkpCXw/F/PczjyMJ6Onmzqu4nSbqW1Lks8TFgYDBgA27er223bwp9/QsmSmpaVExnZEUIIoamUjBQ6LehE6JVQitkVY2PfjVQoUUHrssSDKAr88QdUr64GHUdH+O03WLPGJIMOyMiOEEIIDaVnpvPSopfYHLYZJxsn1vVZR3Wv6lqXJR4kIgJefRXWrlW3mzRRJyCXKaNpWY8iIztCCCE0kanPpM+yPqw6swo7KztW9VpFvZL1tC5L5ERRYN48qFpVDTq2tvC//8GWLSYfdEBGdoQQQmhAr+gZvHIwC48vxNrCmqXdl/Jc6ee0LkvkJCYG3nxTnXQMULs2zJ4NlStrW9djkJEdIYQQBUpRFIavG86MwzOw0Fkwv+t82pVvp3VZIif//KOO5ixeDFZWMG4chIYWqqADMrIjhBCigH2y+RN+3vczADM6zaBr5a4aVyTuExsLw4er83EAqlSBWbPUUZ1CSEZ2hBBCFJiJOyYycedEAH59/lf61eincUXiPiEhUK2aGnR0OvjgAzhwoNAGHZCRHSGEEAXk570/8/HmjwGYFDyJN+q+oXFFwkhiotq8c/JkdbtMGXU0p3FjbevKAxJ2hBBC5Lvph6bz9rq3Afi06ad80OgDjSsSRkJD1ead586p22++CV9/DU7m0XxVLmMJIYTIVwuPL2TwysEAvNvgXcY1G6dxRcIgNRVGjVJHb86dUxcFXL9eHd0xk6ADMrIjhBAiH606s4reS3urt5o/O5j/tf4fOp1O67IEwOHD0Lev2qEc1N//9JPmHcrzg4zsCCGEyBchF0LotrAbGfoMXq72MlPaT5GgYwoyMuCLL6BuXTXoeHjA0qXq2jlmGHRARnaEEELkg92Xd9NpQSdSM1PpVKETMzvNxNLCUuuyxKlT6tyc/fvV7S5dYOpU8PTUtq58JiM7Qggh8tS/1/7l+b+eJzE9kVZlWvF3t7+xtrTWuqyiTa+HH36AWrXUoOPqCnPmwJIlZh90QEZ2hBBC5KETMSdoM7cNsamxNPZvzLIey7C1stW6rKItLAwGDoRt29Tt1q1h2jQoVUrbugqQjOwIIYTIE+dvnid4djDXk65T26c2q3qtwtHGUeuyii5FgT/+gOrV1aDj6AhTpsC6dUUq6ICM7AghhMgDV+Ku0HJ2S64lXKOKRxXW91mPq52r1mUVXRERMHgwrFmjbjdurK6IXLaspmVpRUZ2hBBCPJXoxGiCZwdzKfYS5dzLsbHvRoo7FNe6rKJJUWDBArV555o1YGsL334LW7cW2aADMrIjhBDiKdxMvkmrOa04feM0fi5+bOq7CR9nH63LKpquX1dXPl60SN1+9ln1dvIqVbStywTIyI4QQognEp8aT7u/2nEk6ghejl6E9AshwC1A67KKppUr1dGcRYvA0hLGjIE9eyTo3CEjO0IIIR5bUnoSHed3ZN/Vfbjbu7Op3ybKFy+vdVlFT2wsvPsuzJihbleurI7mFOIO5flBRnaEEEI8lrTMNLot7Ma2S9twtnFmfZ/1VPWsqnVZRc/mzeqdVjNmgE4H778PBw9K0MmBjOwIIYTItQx9Bi8veZm159Zib2XP6pdXU8e3jtZlFS1JSfDRR/Dzz+p2mTLqnVZNmmhalimTsCOEECJX9IqeQf8MYsnJJdhY2rC853KaBMgP2AIVGgr9+8PZs+r2kCHwzTdm1aE8P8hlLCGEEI+kKArD1gxj9n+zsdRZ8ne3v2ldtrXWZRUdqakwapS6Xs7Zs1CypLo44JQpEnRyQUZ2hBBCPJSiKIzcNJIpB6agQ8eszrPoXLGz1mUVHf/9pzbvPHJE3e7bF378EYoV07auQkRGdoQQQjzUF9u/4Jvd3wAwtcNUelfvrXFFRURGBnz5JdStqwYdDw+1cefs2RJ0HpOM7AghhHigH/b8wGdbPwPgu9bf8Vrt1zSuqIg4fVodzdm3T93u3Bl++61IdCjPDzKyI4QQIkd/HPyDd9e/C8C4ZuN4N+hdjSsqAvR69RJVzZpq0HF1VUdyli6VoPMUZGRHCCHEfeYdncfrq14H4P2g9/m06acaV1QEXLwIAweqfawAWrWC6dOLXIfy/CAjO0IIIYysOLWCfsv6oaAwpPYQJrWahE6n07os86UoMG2aukDg1q3g4AC//grr10vQySMysiOEEMJg4/mNdF/cnUwlk77V+zK5/WQJOvnp2jUYPBhWr1a3GzVSFwgsV07TssyNjOwIIYQAYGf4Tjot6ERaZhovVnqR6Z2mY6GTHxP5ZsECtVHn6tVgYwOTJsG2bRJ08oGM7AghhOBAxAHaz2tPckYybcu1Zd6L87CykB8R+eLGDXjzTVi4UN1+9ll1ErJ0KM83EtmFEKKIOxZ9jDZz2xCXGkfTgKYs6b4EWytbrcsyT6tWQdWqatCxtIQxY2DPHgk6+UxiuxBCFGFnb5yl1ZxW3Ey+Sb2S9VjVaxUO1g5al2V+4uLg3XfVu6sAKlVSR3PqSBPVgiAjO0IIUUSFx4YTPCeYyIRIqntVZ23vtTjbOmtdlvnZsgWqVVODjk4HI0bAwYMSdAqQpmFn+/btdOzYEV9fX3Q6HcuXLzc6PmDAAHQ6ndGjbdu2RufcvHmT3r174+LigpubG4MGDSIhIaEA34UQQhQ+kQmRtJzdkvDYcJ4p/gwb+mzA3d5d67LMS1ISvPMOtGgB4eEQGKjeWv6//4G9vdbVFSlPFHZmzZrF6qzb5IAPP/wQNzc3GjZsyKVLl3L9PImJidSoUYPJkyc/8Jy2bdty7do1w2P+/PlGx3v37s3x48fZuHEjq1atYvv27bz2mixnLoQQD3Ij6Qat5rTi3M1zBLgGsKnvJrycvLQuy7zs2QO1asFPP6nbr7+u9rdq2lTbuoqoJwo7EyZMwP5OKg0NDWXy5MlMmjSJEiVK8O67uV9OvF27dnzxxRd06dLlgefY2tri7e1teBS7q/nZyZMnWbduHX/++Sf169encePG/PzzzyxYsICIiIgneWtCCGHW4lLjaPtXW45FH8PHyYeQfiH4ufppXZb5SEuDTz5R18s5cwZ8fWHtWpg6FZyctK6uyHqisHP58mXK3VkHYPny5XTt2pXXXnuNiRMnsmPHjjwtcOvWrXh6elKhQgXeeOMNbty4YTgWGhqKm5sbde667hkcHIyFhQV79+594HOmpqYSFxdn9BBCCHOXlJ5Eh3kdOBBxgOL2xdnUbxNl3ctqXZb5+O8/tUP5hAlqj6veveHYMbhn+oUoeE8UdpycnAyhY8OGDbRq1QoAOzs7kpOT86y4tm3bMnv2bEJCQvj666/Ztm0b7dq1IzMzE4DIyEg872mMZmVlhbu7O5GRkQ983okTJ+Lq6mp4+PnJ/2qEEOYtNSOVLn93YUf4DlxsXdjQdwOVPSprXZZ5yMhQA07duuqlqhIlYPFimDsX7roaIbTzRLeet2rVildffZVatWpx5swZnn/+eQCOHz9OQEBAnhXXs2dPw++rVatG9erVKVu2LFu3bqVly5ZP/LyjRo1ixIgRhu24uDgJPEIIs5WemU7PJT3ZcH4DDtYOrO29lmd9ntW6LPNw+jT07w9ZVxM6dYLffgMvmQNlSp5oZGfy5MkEBQURExPDkiVLKF68OAAHDx7k5ZdfztMC71amTBlKlCjBuXPnAPD29iY6OtronIyMDG7evIm3t/cDn8fW1hYXFxejhxBCmCO9omfgioEsP7UcW0tb/un5Dw39GmpdVuGn16uTj2vVUoOOiwvMmgXLlknQMUFPNLLj5ubGt99+y5EjR4iOjuaff/4BoHbt2nla3L2uXLnCjRs38PHxASAoKIjbt29z8OBBw2tv3rwZvV5P/fr187UWIYQwdYqi8MaqN/jr6F9YWVix6KVFtCzz5KPi4o5Ll2DgQHX9HIDgYHUNHblCYLKeKOysW7eOfv36cePGDRRFMTqm0+kMc2oeJSEhwTBKAxAWFsbhw4dxd3fH3d2dcePG0bVrV7y9vTl//jwffvgh5cqVo02bNgBUqlSJtm3bMnjwYKZOnUp6ejrDhg2jZ8+e+Pr6PslbE0IIs6AoCu9veJ/f//0dHTrmdJlDxwodtS6rcFMUmDEDhg+H+HhwcIBvvoEhQ8BC1ug1acoTKFeunPLmm28qkZGRT/LlBlu2bFGA+x79+/dXkpKSlNatWyseHh6KtbW1EhAQoAwePPi+17xx44bSq1cvxcnJSXFxcVEGDhyoxMfHP1YdsbGxCqDExsY+1fsRQghTMWbLGIWxKIxFmfbvNK3LKfwiIhSlQwdFUSOPojRsqChnzmhdVZGX25/fOkW5Z2gmF1xcXDh06BBly5rHLYtxcXG4uroSGxsr83eEEIXet7u/5YONHwDwY9sfebv+2xpXVMgtXAhvvAE3b4KNDXz+Obz3ntrIU2gqtz+/n2jcrVu3bmzduvVJaxNCCJFPph6Yagg6XzT/QoLO07hxA3r1gh491KBTsyYcOAAffihBp5B5opGdpKQkXnrpJTw8PKhWrRrW1tZGx99+u3D945KRHSGEOZjz3xz6L++PgsJHjT5iQssJ6HQ6rcsqnFavhldfhchINdh8/DGMHq2O7AiTkduf3080QXn+/Pls2LABOzs7tm7davSPSafTFbqwI4QQhd3Sk0sZsGIACgrD6g6ToPOk4uLUruTTpqnbFSvC7NnqgoGi0HqikR1vb2/efvttPvroIyzMYAa6jOwIIQqzdefW8cL8F0jXpzOg5gCmvTANC13h/95c4LZsUW8pv3QJdDp491344gvpUG7C8nVkJy0tjR49ephF0BFCiMJs28VtdPm7C+n6dF6q/BJ/dPxDgs7jSk6GUaPgxx/V7dKlYeZMeO45LasSeeiJ/kX079+fv//+O69rEUII8Rj2Xd1Hh/kdSMlIoX359sx9cS5WFk/0f9iia+9edRXkrKDz2mtqfysJOmblif5VZGZmMmnSJNavX0/16tXvm6D83Xff5UlxQgghcnYk6ght57YlIS2B5qWbs+ilRdhYyuTZXEtLg/HjYeJEtfWDj486T6ddO60rE/ngicLO0aNHqVWrFgDHjh0zOiYT4oQQIn+duXGGVnNacSvlFg1KNeCfXv9gby3zSnLtyBHo1w/++0/dfvll+PlncHfXti6Rb54o7GzJ6gcihBCiQF28fZGWs1sSnRhNTe+arHl5DU42TlqXVThkZMC338Jnn0F6OhQvDlOnQrduWlcm8plc3BVCiEIiIj6C4NnBXIm7QsUSFVnfZz3F7ItpXVbhcOYM9O8Pe/ao2y+8AL//Lh3KiwiZsi+EEIXA9aTrtJrTivO3zhPoFsimvpvwdPTUuizTp9erl6hq1lSDjouLeqfV8uUSdIoQGdkRQggTF5sSS5u5bTgRcwJfZ19C+oVQ0qWk1mWZvkuX4JVXYPNmdbtlS5g+Hfz9ta1LFDgZ2RFCCBOWmJbI8/Oe599r/+Lh4EFIvxACiwVqXZZpUxSYMQOqVVODjr09/PILbNggQaeIkpEdIYQwUSkZKXRa0Indl3fjZufGhr4bqFiiotZlmbbISHWtnJUr1e2gIJg1C8qX17YuoSkZ2RFCCBOUnplO90XdCQkLwdHakbW911LTu6bWZZm2RYugalU16NjYwFdfwY4dEnSEjOwIIYSpydRn0m95P1aeWYmdlR0re62kQakGWpdlum7ehKFDYcECdbtmTbV5Z7VqmpYlTIeM7AghhAnRK3peX/U6C44twMrCisUvLaZ5YHOtyzJda9aoozkLFoClJYwerbaAkKAj7iIjO0IIYSIUReHdde8y7ZDatXzei/No/0x7rcsyTfHxMGIE/Pmnul2hgjqaU6+etnUJkyQjO0IIYSI+3fIpP+37CYDpL0znpSovaVyRidq6FapXzw46w4fDoUMSdMQDyciOEEKYgK93fs2XO74E4Jd2v9C/Zn+NKzJBycnw8cfwww/qdunS6i3mzZppWJQoDCTsCCGExibvm8xHIR8B8FXLrxhab6jGFZmgffvU5p2nT6vbr74K330Hzs7a1iUKBbmMJYQQGpp5eCbD1g4D4JMmnzCy8UiNKzIxaWnw6afQsKEadHx8YPVq+OMPCToi12RkRwghNLLo+CIG/TMIgHfqv8PnzT/XuCITc/SoOppz+LC63auXuhKyu7umZYnCR0Z2hBBCA6vPrOblpS+jV/QMqjWI79t8j06n07os05CZqS4IWLu2GnSKF4eFC2HePAk64onIyI4QQhSwLWFb6LqwKxn6DHpW7clvHX6ToJPl7Fno3x9CQ9XtDh3US1be3trWJQo1GdkRQogCFHo5lI7zO5KamUrHZzoyu/NsLC0stS5Le3q9eomqRg016Dg7qx3K//lHgo54ajKyI4QQBeRw5GHa/dWOxPREWga2ZOFLC7G2tNa6LO2Fh8Mrr0BIiLrdvLl6S3lAgLZ1CbMhIztCCFEATl0/Res5rYlNjaWhX0NW9FyBnZWd1mVpS1Fg5ky1tUNICNjbw08/waZNEnREnpKRHSGEyGcXbl2g5eyWxCTF8KzPs6x+eTWONo5al6WtyEh4/XX1MhVAgwYwaxY884y2dQmzJCM7QgiRj67GXSV4djAR8RFU9qjM+j7rcbNz07osbS1erDbv/OcfsLaGiRNhxw4JOiLfyMiOEELkk+jEaILnBBN2O4yyxcqyse9GSjiU0Los7dy8CW+9pd5CDupk5Nmz1T5XQuQjGdkRQoh8cCv5Fq3ntObU9VOUcilFSL8QfJ19tS5LO2vXqnNz5s0DCwv45BO1BYQEHVEAZGRHCCHyWHxqPM/Pe57/ov7D09GTkH4hBLgV0Qm38fHw3nvqWjmgXqqaPRvq19e2LlGkyMiOEELkoeT0ZDot6MSeK3soZleMjX038kzxIjoXZft29VJVVtB55x04dEiCjihwMrIjhBB5JC0zjW6LurHl4hacbJxY12cd1b2K4GWa5GT1MtUPP6i3lwcEqOvmNG+udWWiiJKwI4QQeSBDn0GfpX1Yc3YNdlZ2rOq1inol62ldVsHbv19t3nnqlLo9aBB89x24uGhblyjS5DKWEEI8Jb2iZ/DKwSw6sQhrC2uW9VjGc6Wf07qsgpWWBp99BkFBatDx9oZVq+DPPyXoCM3JyI4QQjwFRVF4e+3bzDw8E0udJQu6LaBtubZal1Wwjh1TR3MOHVK3e/SAyZPVbuVCmAAZ2RFCiCekKAqjQkYxef9kAGZ0msGLlV7UuKoClJkJkyZB7dpq0HF3hwUL1IcEHWFCZGRHCCGe0IQdE/h619cATGk/hb41+mpcUQE6dw7694fdu9Xt9u3Vu658fLStS4gcyMiOEEI8gR/3/MjoLaMB+KbVNwypM0TjigqIXq9eoqpRQw06zs4wbRqsXClBR5gsCTtCCPGYpv07jeHrhwMw5rkxvN/wfW0LKiiXL0ObNjBsGCQlqbeSHzkCr7wCOp3W1QlTpM+EiHVw+CNNy5DLWEII8RgWHFvA4JWDARjRYARjnhujcUUFQFHUVY/ffhvi4sDODr7+Wg09FvJ/ZpGDuDNwYSaEzYbkq+q+gJehmDbrTknYEUKIXFp5eiV9l/VFQeG1Z1/j29bfojP3EY2oKHj9dVixQt2uXx9mzYIKFbStS5ie9HgIXwgXZkDMruz9Nu5Q+mWwdtasNAk7QgiRC5subOKlRS+Roc+gd7Xe/Nr+V/MPOkuWwJAhcP06WFvD2LHw4YdgJT86xB2KHqK3qwEnfDFkJqn7dRbg0xbKDICSL4ClraZlyt9YIYR4hF3hu+i0oBOpmal0rtiZmZ1nYmlhqXVZ+efWLXjrLfjrL3W7enX1MlaNGtrWJUxHwkUImwUXZkFiWPZ+lwpQZiCU7gsOvpqVdy8JO0II8RD/XvuX5+c9T1J6Eq3LtmZB1wVYWZjxt85169QWDxER6nyckSNhzBiw1fZ/5sIEZCTB5aXqKE7U5uz9Vs4Q0FMNOSUamORkdU1nlm3fvp2OHTvi6+uLTqdj+fLlRscVReGzzz7Dx8cHe3t7goODOXv2rNE5N2/epHfv3ri4uODm5sagQYNISEgowHchhDBXx6OP03pOa+JS42ji34RlPZZha2WmP/QTEtRLVu3aqUHnmWdg1y6YMEGCTlGmKBATCntfg2U+ENo3O+h4tYCgOfBiJNT/HTyCTDLogMZhJzExkRo1ajB58uQcj0+aNImffvqJqVOnsnfvXhwdHWnTpg0pKSmGc3r37s3x48fZuHEjq1atYvv27bz22msF9RaEEGbq/M3ztJrTihvJN6jjW4dVL6/CwdpB67Lyx/bt6qWq335Tt99+W10RuUEDbesS2kmKgBNfw+rKsLEhnP8D0uPAsTRUGwsvhEHLEAjsA1am/+9CpyiKonURADqdjmXLltG5c2dAHdXx9fXlvffe4/331TUsYmNj8fLyYubMmfTs2ZOTJ09SuXJl9u/fT506dQBYt24dzz//PFeuXMHXN+frhampqaSmphq24+Li8PPzIzY2FhdpWCdEkXc59jJNZjThUuwlqnpWZWv/rRR3MMP2Bykp8Mkn8P336v/g/f1hxgxo0ULryoQWMlPh6kr1MtW1derkYwBLB/Dvpk429nxOnXxsIuLi4nB1dX3kz2/TqfgeYWFhREZGEhwcbNjn6upK/fr1CQ0NBSA0NBQ3NzdD0AEIDg7GwsKCvXv3PvC5J06ciKurq+Hh5+eXf29ECFGoRCVEETwnmEuxlyjvXp6NfTeaZ9A5cACefRa++04NOq+8oi4QKEGnaFEUuPkvHHgblvnCzpcgYo0adDwaQf0/4cVrEDQLvJqbVNB5HCY7yy4yMhIALy8vo/1eXl6GY5GRkXh6ehodt7Kywt3d3XBOTkaNGsWIESMM21kjO0KIou1m8k1azWnFmRtn8Hf1Z1O/TXg7eWtdVt5KT4cvvoAvv1QbeXp5qT2tOnbUujJRkFJi4OJf6ijO7SPZ++1LQmA/dRTH5RnNystrJht28pOtrS22MuFOCHGXuNQ42v3VjqPRR/F28mZT3034u/prXVbeOnYM+vVT5+MAdO8Ov/4qHcqLCn0GRKxVA07EKtCnq/stbKBUZ/VuKu9WYIbLKphs2PH2Vv83FRUVhc9dzeWioqKoWbOm4Zzo6Gijr8vIyODmzZuGrxdCiEdJSk+i4/yO7Lu6D3d7dzb23Uj54uW1LivvZGaql6tGj4a0NHB3V0NOjx5aVyYKQuwJNeCEzYGUqOz97rXVgBPQC2zdtauvAJhs2AkMDMTb25uQkBBDuImLi2Pv3r288cYbAAQFBXH79m0OHjxI7dq1Adi8eTN6vZ769etrVboQohBJzUil68KubL+0HWcbZ9b3WU9Vz6pal5V3zp2DAQPU28gBnn8e/vxTOpSbu7TbcGmBGnJu7Mveb+sBpftA2YHgVk2z8gqapmEnISGBc+fOGbbDwsI4fPgw7u7u+Pv7M3z4cL744gvKly9PYGAgn376Kb6+voY7tipVqkTbtm0ZPHgwU6dOJT09nWHDhtGzZ88H3oklhBBZMvQZ9FrSi3Xn1mFvZc+a3muo41vn0V9YGCgKTJ0K77+vdih3coIffpAO5eZMnwlRIWrAubwM9HfuOtZZQcn26iiO7/NgYa1tnRrQNOwcOHCA5s2bG7azJg3379+fmTNn8uGHH5KYmMhrr73G7du3ady4MevWrcPOzs7wNX/99RfDhg2jZcuWWFhY0LVrV3766acCfy9CiMJFr+h5ZcUrLDu1DBtLG1b0XEFj/8Zal5U3Ll9WV0HeuFHdbtZMvaW8dGktqxL5Jf7cnQ7jsyDpSvZ+16pqwAnsA3aeD/zyosBk1tnRUm7v0xdCmAdFUXhz9ZtMPTgVS50lS7ovoVPFTlqX9fQUBebMURcFjI0FOzv46iu1z5VF4bxlWDxAegKEL7rTYXxH9n5rN7XDeJmB6pwcMx/Fy+3Pb5OdsyOEEPlBURQ+3PghUw9ORYeOOV3mmEfQiY6G11+HrLY79erBrFlQsaKmZYk8pChqsLkwQw06GYl3DujAp7UacEp1Aku7hz5NUSRhRwhRpHy+/XO+Df0WgN86/Eavar00rigPLF2qBp3r18HaWm3cOXIkWMm3eLOQGA5hs9VLVQnns/c7l1fXwwnsBw6ltKquUJB/CUKIIuO70O8Ys3UMAN+3+Z7BtQdrXNFTunVLvWQ1d666Xa0azJ4Nd+5gFYVYRjJcWaaO4kSGAHdmnFg5QUCPOx3GG5r9Zaq8ImFHCFEk/H7wd97b8B4A45uNZ3iD4doW9LTWr1cnIV+9qs7HGTlSHdGRBVMLL0VRbxO/MEO9bTw9NvuYZzM14Ph3BStHzUosrCTsCCHM3l9H/mLIqiEAfNDwA0Y3Ha1xRU8hIQE++EC9rRygfHl1bk5QkLZ1iSeXHKku+HdhBsSdzN7vGACB/aFMf3Aqo119ZkDCjhDCrC07uYz+y/ujoPBGnTf4OvhrdIV16H/HDnWBwAsX1O1hw9S7rRzlf/qFTmaa2rLh/Ay4thaUTHW/pR34dVVHcQpx401TI2FHCGG2NpzfQM8lPclUMulXox+/PP9L4Qw6KSlqq4esDuV+fuq6OS1bal2ZeFy3DqsTjS/+BanXs/eXCLpzmao72LhqVZ3ZkrAjhDBLOy7toPOCzqRlptG1UlemvTANi8L4v+QDB9TmnSfvXN4YOBC+/x5c5QdioZF6I7vD+K3D2fvtfdQ7qQIHgKssEZCfJOwIIczO/qv7aT+vPckZybQr1455XedhZVHIvt2lp8OXX8IXX6iNPL284Pff4YUXtK5M5IY+A66tVwPO1X+MO4yXfEEdxfFpDYXt72UhJZ+yEMKsHIs+Rtu/2hKfFs9zAc+xpPsSbCxttC7r8Rw/ro7m/Puvut2tG0yZAiVKaFuXeLTYU2rAuTgHkq9l7y9WSw04pV8G2+La1VdESdgRQpiNszfOEjw7mJvJN6lfsj4re63E3tpe67JyLzNTvUQ1ejSkpkKxYjB5MvTsKeupmLK0WAj/W51sfGNP9n7bElC6txpyitXQrj4hYUcIYR4u3b5Ey9ktiUqMorpXddb2XouzrbPWZeXe+fPqnVY7d6rb7drBn3+Cr6+mZYkHUPQQtVkNOFeWQmaKul9nqXYWLzMQfNtDYRtVNFMSdoQQhd61+GsEzwnmctxlnin+DBv6bKCYfTGty8odRYHffoP334fERHByUkd3Bg2S0RxTlHBBvZvqwixICs/e71r5zmWqPmDvrVl5ImcSdoQQhdr1pOu0mtOKczfPUdqtNCH9QvBy8tK6rNy5ckUNNRs2qNvPPafeUh4YqG1dwlhGIoQvVufiRG/L3m/tCgG91JBTvK6EUxMmYUcIUWjFpsTSdm5bjsccx8fJh019N1HKpRA0RFQU+OsvdVHA2Fi1xcPEifDOO2rrB6E9RYGYXXc6jC+EjIQ7B3TgHXynw3hnsCpEc8KKMAk7QohCKTEtkQ7zO3Dw2kFKOJRgU79NlHUvq3VZjxYdDW+8oXYqB6hbV233UKmStnUJVdIV9RLVhZmQcC57v1NZNeAE9gNHP83KE09Gwo4QotBJyUihy99d2Bm+E1dbV9b3WU9lj8pal/Voy5bB669DTAxYWamNOz/6SP290E5mClxefqfD+EayO4w7qisalxkIHo3lMlUhJv/ChBCFSnpmOj0X92TjhY04WjuypvcanvV5VuuyHu72bXj7bZgzR92uWhVmz4ZatTQtq0hTFLh54M6aOPMh/Xb2Mc+masDx6wbWTpqVKPKOhB0hRKGRqc9kwIoBrDi9AltLW1b0XEFDv4Zal/VwGzbAK6/A1avqfJwPPoBx49R5OqLgJUfBxblqyIk9nr3fwe9Oh/EB4FwILoeKxyJhRwhRKCiKwpBVQ5h3VG39sLj7YlqWMeFGmAkJ8OGH6srHAOXKqXNzGpp4ODNH+nS4uloNOBFrQMlQ91vaQakX1YDj1QIsLDUtU+QfCTtCCJOnKAoj1o/gz0N/YqGzYG6XuXR4poPWZT3Yzp3qAoHnz6vbQ4fC11+Do6OmZRU5t47c6TA+F1JjsvcXr69epgroATZuWlUnCpCEHSGEyRuzdQw/7P0BgD86/kGPqj20LehBUlLg00/hf/9T54T4+cH06RAcrHVlRUfqTbg4706H8X+z99t5Q2BfdRTHtRBMZhd5SsKOEMJkHbp2iE82f8Lac2sB+KntT7xS6xWNq3qAf/9Vm3cevzMPpH9/+PFHcHXVtq6iQJ8JkRvUgHNlBejT1P0W1lCy450O422lw3gRJn/yQgiTc/r6aT7d8imLTiwCwFJnyVfBX/FW/bc0riwH6ekwYQJ88QVkZICnJ/z+O3TqpHVl5i/ujBpwwmZDckT2frcad1o39AY76RQvJOwIIUxIeGw447aOY+Z/M9ErenTo6FWtF+OajaOcezmty7vfiRPqaM7Bg+p2t27qhOQS8gM236THwaWFasi5vjt7v21xCOgNZQdCsZqalSdMk4QdIYTmohOjmbBjAlMOTCEtU70E8UKFF/i8+edU96qucXU5yMyEH36ATz6B1FRwc4PJk6FXL1l4Lj8oeojaqk42vrwYMpPV/ToL8GmnjuKU7ACWcju/yJmEHSGEZm6n3Obb3d/yw54fSExPBKBZ6WZMaDGBIL8gjat7gAsX1DutduxQt9u2hT//hJIlNS3LLCVcVANO2CxIvJi936XindYNfcHeR6PiRGEiYUcIUeCS0pP4ee/PfL3ra26l3AKgrm9dJrScQMvAluhMcXREUdS5OO+9B4mJ6m3k330HgwfLaE5eykiCy0vUy1RRW7L3W7tAQM87Hcbry2cuHouEHSFEgUnLTOOPg3/wxY4viEyIBKCyR2W+aP4FnSt2Ns2QA+rqx4MGwfr16nbTpjBjBpQpo21d5kJR4HqoGnAu/Q0Z8XcO6NTF/soMBL8uYOWgaZmi8JKwI4TId5n6TP46+hdjto7h4u2LAAS6BTKu2ThervYylqa6cq2iwLx5MGyY2t/K1hYmToR33lFbP4inkxSh3kkVNhPiTmfvdyoDgQOgTD9wDNCqOmFGJOwIIfKNoigsO7WM0ZtHc/L6SQC8nbz5tOmnvPrsq9hY2mhc4UPExMCQIbB0qbpdp47avLNSJW3rKuwyU+HqP3B+BkSuVycfA1g6gP9L6iiOZxN18rEQeUTCjhAizymKwqYLm/h488cciDgAQDG7YnzU+COG1RuGg7WJX45YsQJeew2io8HKCj77DD76CKytta6scFIUdTXj8zPg0jxIu5V9zKOxGnD8XwJrZ+1qFGZNwo4QIk+FXg7l480fs/XiVgAcrR15t8G7vNfwPdzs3DSt7ZFu31YvUc2erW5XqaL+/tlnNS2r0EqJye4wfvto9n77klCmv3qpyqW8ZuWJokPCjhAiTxyJOsLozaNZeWYlADaWNrxZ501GNRmFp6OnxtXlwsaN8MorcOWKeqfPBx/A+PHqPB2Re/p0iFirBpyrq7I7jFvYQqnO6iiOd7B0GBcFSsKOEOKpnL1xljFbx7Dg2AIUFCx0FgysOZDPnvsMf1d/rct7tMRE+PBD+PVXdbtsWZg1Cxo10rauwub2cTXgXJwDKdHZ+93rqqsaB/QEm2La1SeKNAk7QognciXuCp9v+5xph6aRqWQC0KNKD8Y1G0eFEhU0ri6Xdu1SG3aeP69uv/kmTJqkrqEjHi3tFlxaoM7Fubk/e7+dJ5S+02Hcrapm5QmRRcKOEOKxxCTG8NXOr5i8fzKpmakAPF/+eb5s8SU1vWtqW1xupaTAmDHwzTfq5NlSpWD6dGjVSuvKTJ8+EyI33ekwvhz06t8BdFZqy4YyA8G3ndpxXAgTIWFHCJErcalx/G/3//huz3ckpCUA0MS/CRNaTqCxf2ONq3sM//6rNu88flzd7tcPfvxR7W8lHizurLoeTthsSLqSvd+t2l0dxgvB3CxRJEnYEUI8VHJ6MpP3T2bizoncTL4JQC3vWkxoOYE2ZduY7qrH90pPVxcE/PxzyMgAT0/47Tfo3FnrykxXejyEL1JHcWJ2Zu+3KQYBL9/pMP6stG4QJk/CjhAiR+mZ6Uw/NJ3x28cTER8BQIXiFfiixRe8WOlFLArTom8nT6ojOAfUNX948UWYOhU8PLStyxQpeojeoQac8EWQmaTu11mAdxs14JTsCJZ22tYpxGOQsCOEMJKpz2TBsQV8tvUzLty6AIC/qz9jnxtL3xp9sbIoRN829Hr44Qf4+GNITVUvVf3yC7z8soxG3CvxElyYpXYYT7iQvd/5mewO4w7S2V0UToXou5YQIj8pisLKMyv5ZPMnHIs+BoCnoyejm4zmtdqvYWtVyNabuXABBg6E7dvV7TZt4M8/1cnIQpWRDJeX3ukwvhlQ1P1WzhDQQw05JYIkGIpCT8KOEILNYZv5OORj9l7dC4CbnRsfNvyQt+u/jaNNIbsNW1Hgjz9gxAh1DR1HR/jf/9T2D/JDW/18buy902F8AaTHZR/zan6nw/iLYFXI/tyFSbp1S70X4MQJePVV7frnStgRogjbd3Ufn2z+hE0XNgHgYO3AO/Xf4YOGH1DMvhAuAHf1qvoddd06dbtxY5g5U10osKhLvgZhc9SQE3cqe79jwJ0O4/3BKVCz8kThFhenBprjx9XHsWPqrxER2ee0bg2lS2tTn4QdIYqgY9HH+HTLpyw/tRwAawtrXq/9Op80/QRvJ29ti3sSigLz58PQoWp/K1tb+PJLGD4cLItwW4LMVLi6Ei7MhGvr4M7ij1jag183dbKx53PSYVzkWmKiOt//7kBz/DiEhz/4a/z81DZzyckFV+e9JOwIUYRcuHWBMVvH8NeRvwytHfrV6MeY58ZQ2q201uU9mZgYeOMNWLJE3a5dW23eWbmytnVp6eahO5ep5kHqjez9JRqql6kCuoO1i3b1CZOXkgKnTt0fasLC1P9b5MTHRw01Vauqv1apov4zdHUt2NpzYtJhZ+zYsYwbN85oX4UKFTh1Sh2CTUlJ4b333mPBggWkpqbSpk0bfv31V7y8vLQoVwiTFREfwRfbv+CPf/8gQ682ZuxaqSufN/+cSh6VNK7uKfzzDwweDNHRYGUFo0erd15ZF8HVe1Ouw8W/7nQY/y97v70vBPZTWze4FJI2HqLApKXBmTP3h5pz59SbGXPi4XF/qKlSBdzdC7b2x2HSYQegSpUqbNq0ybBtZZVd8rvvvsvq1atZtGgRrq6uDBs2jBdffJFdu3ZpUaoQJudG0g2+3vU1P+/7mZSMFADalG3DFy2+oI5vHY2rewqxsfDOO2rDTlD/+zh7tjqqU5ToM9TLUxdmqJer9OnqfgsbKNXpTofx1tJhXJCRoQaYuwPNsWNw9qx6LCfFihkHmqzfF8blqUw+7FhZWeHtff8cgtjYWKZNm8a8efNo0aIFADNmzKBSpUrs2bOHBg0aPPA5U1NTSU1NNWzHxcU98FwhCqP41Hh+2PMD34Z+S1yq+ve7oV9DJrSYwHOln9O4uqe0aRO88gpcvqzeXfX++zB+PNgVoUXuYk+qASdsDqREZu93r61ONi79Mtia8H+zRb7JzFQvNd0bak6fVkdxcuLsnHOo8fY2nxsYTT7snD17Fl9fX+zs7AgKCmLixIn4+/tz8OBB0tPTCQ4ONpxbsWJF/P39CQ0NfWjYmThx4n2Xx4QwBykZKUw9MJUJOyYQkxQDQA2vGnzZ4kueL/984WntkJPERBg5EiZPVrfLlFFHdhoXor5cTyPttnqr+IUZcGNf9n5bDyjdR71MVay6VtWJAqbXq5OC7w01J0+q821y4uBgfNkpK9SUKmU+oeZBTDrs1K9fn5kzZ1KhQgWuXbvGuHHjaNKkCceOHSMyMhIbGxvc7mne5+XlRWRkZM5PeMeoUaMYMWKEYTsuLg4/P7/8eAtCFIgMfQYzD89k3LZxXIlTmzSWdy/P580/56UqLxWu1g452b0b+vdXx+FBnZA8aRI4OWlbV35T9BAZcqfD+DLIvPNTTGcJvu3vdBh/HixttK1T5BtFUVdUuDfUnDih5v+c2NlBpUr3z6sJCNBunRutmXTYadeuneH31atXp379+gQEBLBw4ULs7e2f+HltbW2xtS1kq8EKkQO9omfh8YV8tuUzzt48C0Apl1KMeW4M/Wv0x9qyEE/UjYxU77BauBB27FC/65csCdOnqwt2mLP48+rt4mGzIOly9n7XKnc6jPcBe7kRw5woivpXPivQ3D1h+EEzLaytoWLF+0NNmTJFe8WFnJh02LmXm5sbzzzzDOfOnaNVq1akpaVx+/Zto9GdqKioHOf4CGFOFEVhzdk1fLL5E/6LUu+8KeFQgk+afMKQOkOwsyqk81eio2HpUvj7b9i2zfge17594ccf1VmT5ig9AS4vVkdxordn77d2g9K91JDjXsf8rzcUATEx9wea48fh5s2cz7e0hGeeuT/UlCtXNG88fBKFKuwkJCRw/vx5+vbtS+3atbG2tiYkJISuXbsCcPr0acLDwwkKCtK4UiHyz7aL2/h488fsvrwbABdbF94Pep/hDYbjbOuscXVP4Pp1NeAsXAhbthjf71q/PnTvDt26gb+/djXmF0WBmJ13OowvhIys6xI68GmtBpxSnaTDeCGV1Srh3lATHZ3z+RYW6mLf997S/cwz6jqZ4smZdNh5//336dixIwEBAURERDBmzBgsLS3p1asXrq6uDBo0iBEjRuDu7o6LiwtvvfUWQUFBD52cLERhdTDiIJ9s/oT159cDYGdlx1v13mJko5EUdyiucXWP6eZNWLZMDTghIeotJFnq1FEDzksvabe2fH5LvAxhs9VLVQnnsvc7lVNXNQ7sBw7SsLSwuLtVwt2h5u5WCfcKDLz/DqgKFeApZmiIhzDpsHPlyhV69erFjRs38PDwoHHjxuzZswePOzf5f//991hYWNC1a1ejRQWFMCcnY07y6ZZPWXJSXSHYysKKwc8OZnTT0fg6+2pc3WO4dQtWrFADzsaNxot71KqlBpzu3dUJB+YoIxmuLFdHcSI3kd1h3An8u6ujOB6N5DKVCctqlXDvZOHLlx/8Nf7+99/9VKmS2p9WFBydojxo4eeiIy4uDldXV2JjY3FxkSXUhWm4ePsi47aNY/Z/s9ErenTo6FO9D2ObjaVMsUISCGJj1VWOFy6E9eshPT37WPXq2QGnfHntasxPigI39t9p3TAf0mOzj3k+pwYc/27SYdzEZLVKuDfUXLz44FYJvr73h5rKlUF+pOSv3P78NumRHSGKosiESL7c/iW/HfyN9Dsr4nau2JnPm39OVc+qGleXC/Hx2QFn3TrjlcyqVs2+RFWxonY15rfkSLg4Vw05sSey9zv4q+vhlOkPToUksJqxrFYJ94aa8+cf3CrB0/P+UFOlivnOmzcXEnaEMBG3km/xze5v+HHvjySlJwEQXCaYL1t8Sb2S9TSu7hESEmDVKjXgrFkDd61QTsWK0KOHGnCqVNGuxvyWmQYRq9WAE7Hmrg7jduDXVR3F8WouHcY1kJGhtkW4d7Lww1oluLvn3P+pMLZKEBJ2hNBcQloCP+39iUm7JhGbql7mqF+yPhNaTqBFYAuNq3uIxEQ12CxcCKtXQ3Jy9rHy5dWA06OH+hPCnOeh3PpPnWh8cS6kXs/eX7yBOtnYvwfYmEDb5yIgMxMuXLg/1DysVYKLy/2hpmpV8PIy77+2RY2EHSE0kpqRyu8Hf+eLHV8Qnajei1rVsypftviSjs90NM3WDsnJsHatGnBWroSkpOxjZcuql6h69FDn45hi/Xkl9QZcnKeO4tw6lL3fzju7w7hrIe4mb+L0erh06f5Q87BWCY6O6hyae0NNyZLm/VdVqCTsCFHAMvQZzPlvDmO3jSU8NhyAMsXKML7ZeHpW7YmlqXWoTklRJxf//bcacBISso+VLq2Gm+7d1TuqzPmnhj4Drm2402H8H9DfGSqwsIaSL6iXqXzagIV8W80rigJXrtx/S/ejWiVUrnz/vBp//6LbKkFI2BGiwOgVPUtPLuXTLZ9y6vopAHydffms6We8UusV02rtkJoKGzaoIzgrVqiTjrP4+2ffRVWnCKzoG3f6Tofx2ZB8LXt/sVp3Wje8DLaFbJ0jE3N3q4S7Q83DWiXY2GS3Srg71AQGSqsEcT8JO0LkM0VRWH9+PZ9s/oR/r/0LgLu9O6Maj2Jo3aHYW5vIKmJpabBpkxpwli9XbxvPUqqUOsG4e3d1VWNzDzjpcXDpbzXkXA/N3m9b/E6H8YFQrIZ29RViWa0S7r0D6tatnM+3sspulXB3qClXTj0mRG7IXxUh8tHO8J18HPIxO8J3AOBk48R7Qe8xImgELrYmsABHejps3qwGnGXLjH/i+PpmB5wGDcz/GoCih6itasC5vAQy70y41lmCTzt1srFvB+kwnks3b+bc1DImJufzLSzUAHPvZOFnnlFHcYR4GhJ2hMgHh64dYvSW0aw5uwYAW0tbhtYdykeNP8LDUeN7VzMyYOtWNeAsXQo3bmQf8/LKDjiNGpl/wAFICMvuMJ54KXu/SyV1BCewD9j7aFaeqYuLyznUXLuW8/k6nXqp6d5QU7GiOt9GiPwgYUeIPHTmxhk+3fIpC48vBMBSZ8mgWoP49LlPKeWiYa+jzEzYvl2dZLxkidp8M4uHh9pos3t3aNKkaEx4yEiE8CV3Ooxvzd5v7QoBPdWQU7ye+V+uewyJidn9n+4ONblplXB3qJFWCUILEnaEyAPhseGM3zaemYdnknlnMbleVXsxrtk4yhfXqBVCZibs3KmO4CxZAlFR2ceKF4euXdWA89xzRWPyg6LA9d13WjcshIysSdc68A6+02G8M1iZyBwqjSQnq60S7p1XExb24K/x9b1/8T1plSBMSRH4DidE/olOjGbijon8euBX0jLVW5E7PtORz5t/Tg1vDSaw6vWwe7cacBYvNr6WUKwYvPiieqt4s2ZgbUJ3f+WnpKvZHcbjz2TvdyqrrocT2A8c/bWqTjNpaepie/eGmke1Srh3nZrKlaVVgjB9EnaEeAKxKbF8u/tbvt/zPYnp6oIfzUo3Y0KLCQT5BRVsMXo97N2rBpxFi+Dq1exjrq7QpYsacFq2LDoBJzMFrqy402F8ozr5GNSGm/4v3ekw3qRIXKZKT4dz5+4PNWfOqIN/OXF3zw41d4ebEiUKtnYh8oqEHSEeQ1J6Er/s+4Wvdn7FrRT1zqU6vnWY0GICwWWCC27VY0WB/fvVgLNwofHECRcX6NxZvUTVqlXRuZVFUeDmwewO42l33Vnm0eROh/GXwNpJuxrzUVarhHvXqTl1yrjZ/N1cXXNuaimtEoS5kbAjRC6kZabx579/8vn2z4lMiASgskdlvmj+BZ0rdi6YkKMo8O+/6iTjhQvV9fKzODlBp05qwGndumjd1pISDWFZHcaPZe93KAWB/dVLVc7lNCsvr2W1Srh3nZpTpx7cKsHJKXtV4btDjbRKEEWFhB0hHiJTn8m8o/MYs3UMYbfVGZql3Uozrtk4elfrnf+tHRQFDh/OHsG5cCH7mKMjdOyoXqJq0wbsi9DEWn262ln8wgy4uhqUO62rLWzB78U7HcZbgKm13ngMWa0S7g01J08+uFWCvb16t9O982r8/IrGKgJCPIiEHSFyoCgKy08tZ/SW0ZyIOQGAl6MXnzb9lMG1B2OTnwvLKQocPZodcM6ezT7m4AAdOqgjOO3aqdtFye2j2R3GU6Kz9xevpwacgJ5g46ZVdU9EUdR55PeuVXPixKNbJdwbakqXLhorBwjxuCTsCHEXRVEICQvh45CP2R+xH4BidsUY2Wgkw+oNw9EmHxcIOX48O+CcOpW9384O2rdXA0779kVrkZLMVIg9DjG71EX/bh7MPmbnBYF9IXAAuFXRrMTHER19/zo1x48/ulXCvaGmbNmisVqAEHlF/rkIcceeK3v4OORjtlzcAoCjtSPvNniX9xq+h5udW/686KlT2XNwTpzI3m9rq47cdO+ujuQ4O+fP65uStFi4/R/cPAS3DsGtw2rQybpEBaCzgpId1VEc37Zqx3ETdHerhLtDzcNaJZQvf/9k4fLli878ciHyk4QdUeQdjTrK6C2j+ef0PwDYWNrwRp03GNV4FF5OXnn/gmfOZI/gHD2avd/GRp170707vPCC+a7IpiiQEnlXqLnzSLiQ8/k27mqH8ZIdoHRvsNO43cZdYmPVjHrvHVAPa5VQpsz9oaZChaI1p1yIgiZhRxRZ526eY8zWMcw/Oh8FBQudBQNqDGBMszH4u+bxInPnz2cHnMOHs/dbWal3T/XooQYcN7e8fV2tKXqIP6eO0twdbO6eb3M3B39wr6WGm2I11V8d/DS/ZSghQZ0YfO9k4StXHvw1AQH3h5pKlYreNCshTIGEHVHkXI27yvht45l2aJqhtUP3Kt0Z32w8FUpUyLsXCgtTF/lbuBAO3jXXxMoKgoPVEZzOnc1n+dms+TVZl6BuHYJb/0FGwv3n6izApeKdUJP1qAG2xQu87LtltUq4N9RcvPjgrylZ8v5buitXLhpXHoUoLCTsiCLjetJ1vtr5Fb/s+4XUzFQA2pVrx5ctvqSWT628eZHwcDXg/P23uuhfFktLaNFCDThduqi9qQqz9Dg10Nw8BLfv/Hrv/JoslnbgVt042LhVBSvthjhSU7NbJdwdai5ceHCrBC+v+0NNlSrmNxgnhDmSsCPMXlxqHN+Ffsd3od8Rn6Y2f2zs35gJLSbQJKDJ07/AlSvZIzh79mTvt7BQe1B17672pPIwnbkmjyX52j3zaw5Dwvmcz82aX5N1Ccq9Fjg/AxbafKtJT1fv3L93svDZsw9ulVC8eM6hRlolCFF4SdgRZis5PZlf9//KxJ0TuZF8A4Ba3rX4ssWXtC3X9ulWPY6IUBttLlwIu3Zl79fpoGlTdQ7Oiy+qwwGFhaKH+PPGc2tuHYaUqJzPz5pf41Yze56NRvNrMjPVaVH3hprTpx/eKuHeQFO1qtrsUlYVFsK8SNgRZic9M50Zh2cwftt4rsarTTErFK/A580/p2vlrljonnAp2chIWLJEDTg7dqh3FYH6k7FxY3UEp2tX8PHJo3eSjwzzaw7fFWxyM7+mZvavGsyv0evV+TP3hppHtUq4N9BUqQK+vhJqhCgqJOwIs6FX9Cw4toDPtnzG+VvqZRZ/V3/GPjeWvjX6YvUkl1Kio2HpUnUOzrZt2QEHoGFDNeB066bOUjVVOc2viTuhtly4133za2qCW7UCm1+jKOoCe5cvq1cHsx7h4eot3idOQFJSzl9rb59z/yd/fwk1QhR1EnZEoacoCqvOrOKTzZ9wNFpdt8bT0ZNPmnzC67Vfx9bK9vGe8Pp1WLZMDThbthjPWK1fPzvg+Ofx7el5wWh+zeE769c8aH5NsXvuhqoJLhXybX6Noqgf7d0h5sqV+4NNcvLDn8fWVm2VcG+oCQyU/k9CiJxJ2BGFjqIonL5xmi1hW9h6aStbL24lOlFdt8XV1pUPG33I2/XfxsnGKfdPevOmGnAWLoSQEOPZq3XqqAHnpZfU5kOm4LHn1/hlh5p8mF+j16urAz8sxFy5ot4FlRseHlCqlNrAslQp9VGhghpqpFWCEOJxybcMYfIUReH8rfNsCdvClotb2HpxK9cSjJeodbR25K16b/FBow9wt3fP3RPfugUrVqgBZ+NGyLjrtulnn80OOGXK5OG7eQKZqRB74p5g84j5NXdPGn7K+TWZmerVvIeFmKtXIS0td8/n5WUcYrIeWft8fWU1YSFE3pKwI0xS2K0wQ7DZcnELV+KMl6q1tbSloV9DmpduTrPSzahXsl7uLlfFxsI//6gBZ/1641t1atTIDjjly+fxO8ql9Dg1yGSFmlzPr6l5Z/2ax5tfk5mpzrt+UIi5fFm98Swjh+Vz7qXTqXOzHxRisoKM9HoSQhQ0CTvCJFyOvcyWi+rIzZawLVyKvWR03NrCmgalGtC8dHOaBzanQakG2Fnl8r//8fGwcqUacNauNR6CqFo1O+BUrJiH7ygXsubXZE0azvX8mprqr4+YX5ORoQaVewPM3cHm2rUHrzdzNwsLNag8KMSUKqUGHWvT7MsphCjiJOwITUTER6hzbu6M3GTdPZXFysKKeiXr0SygGc0Dm9PQryEO1o9xR1BCAqxapQacNWuMJ4tUrKiug9O9u3r7Tn67b37N4Tv9oXIxv6ZYTfVylIPxLUVpaRAR/vA5MpGRD14N+G6WlurNZA8KMaVKgbe3zJMRQhRe8u1LFIiohChDsNlycQtnbpwxOm6hs6CObx115KZ0cxr5N3q8Ccag3pO8erUacFavNr6t55lnsgNOlSr5dy9yZtpd/aFyMb/GuYLxpOFiNUmlOFev3gktx3K+vBQVZXwX/INYW2cHmQfNk/H0VAOPEEKYKwk7Il9cT7rO1otbDQHnRMwJo+M6dDzr8yzNSjejeenmNAlogouty+O9SExM9spyO3eql6ruXoSlbNnsgFO9et4HnMedX+NajQyXWtykFpcTanE6qhqXjjrcNzoTE5O7l7exeXiIKVVKvatJbscWQhR1EnZEnriVfIttl7YZ7pjKWu/mbjW8ahjm3DQNaIqbnVvunjwuLjvU3P2Ijr7/3MBANdx07w61auVdwEm+ln356RHza9J1xbieWYtL8TU5ea0WB87XYs+JCly6bMWNG7l7OTu7h4eYUqXUXk2yWJ4QQjyahB3xRGJTYtkRvsMQbg5HHkbB+LpKFY8qhnDzXMBzFHd4xO3Pycnquv/3hprw8Ad/TZky6iTj6tXhhRfUNXGeJgEYza85nD1q84D5NdGJfhyPqMX+szXZfaoWhy7VIvy6P/DgGhwc7g8y9267u0uQEUKIvCJhR+RKfGo8O8N3Gubc/HvtX/SK8ezXiiUqGubcPFf6OTwdPXN+sqxW1PeGmvPnHzyjtmRJNdRkPapUUScXOzo++ZvKTEO5fZzka4dIvnoIi9jDOKb/h40u/v5T9RacvlaBQxdrcehiLQ5fqsnhSzW5kWDcCtvJCSpVevhkXzc3CTJCCFGQJOyIHCWlJ7ErfJch3Oy/up9Mxfge5XLu5QzhplnpZvg439MAU6+HsLDsbo1ZoebUqQe3oi5e3DjUZAWbYsUe+z0oCty+fefOpMtxJEf8h2X8IVwzD+Fte5gAt+NYW6bjABju89JBcpodRy9XU4PNJTXYHAmvjo29gyGwBAZBk5fuH51xecxpR0IIIfKfhB0BQHJ6MqFXQg2XpfZd3Uf6PRNtA90CDZelmpVuRimXUuoBRVEXdNm93nik5mFdG52c7g81VauqtwY9YthDr1cXP46JyX7cvcJv4o1I3PSH8HU4RFXfQ9QKOEQr7/MYpxrVrUQ3Dl2sxcnIWlxJqkWsriaKc0V8S1lRqjF07QnD/dSBJWfnJ/xwhRBCaErCThGVmpHK3qt7DeFmz5U9pGYaNy7yc/GjeWBzw+hNgFuA2snx2DHYvjw71Bw/rg6h5MTWVr3clDVCkxVq7mpFnZGhPm1MNMQcNw4xMTF3jt21fftWBiWcovBxu4ZvsQh83K5R2uMijQIOU6veIbzdcp5fE5Pox7WUmsRa1CLduRZ2PrUoUduf+i/raPEUV8OEEEKYNgk7RURaZhr7r+43XJbafXk3KRkpRuf4OvsaLkm1cK9D4LVkdMePw9bDcGyuGmyiHrAQnqWlupZN1aqkV6xKbKmqRHlU5aptGaJvWmWHleUQ84dxiLl1S30KW+sUvF0j8XG7ZggyJd2uUcftGj6B1wz7PZxjsLB48CIzesWCZOsK6F1qYudTC2uvWuBWEw+7EnjkzccphBCiEJGwY6Yy9BkcjDhoCDc7w3eSlG58ScnT0ZPWPk3oRAUaxbniHXYdXchxOPb5Q++AivMoQ5RHVcKdq3LGpirHlCocTq5AxA1bYtZA4iLj8x1tE9SgUkwNK6XdrhHkfw3fGhGGAOPjdg13p1u5fn+KzhKdnRfY+4CdDziUgmJqnygLt2o4WslQjRBCCJWEnUIsLTONS7cvcfH2RcJuhxn9ejz6OPFp2XcVWWVCUKIrL+orEnTTnTLh6bieD8f+6jJ0D7gDKtLCl6NKVY4oVTmG+jhJJRJjnCBGwc3htiHABLodoWGV7OBS0j2CksWv4e1yDUfbHFYPfhALm+wAY+8D9r53fr3rYeeDzrYEWMiyv0IIIR5Nwo4Jy9BncCXuCmG3wnIMNFfjrhqtbWOVCSWSwCsBmsVCzSg7akWUoFJUJmViY7BRYoG9973ODdw5SjWOUZXjuspcdvYj1s0NR7dEQ3ipV+JfXvJcTUn3a3i5RuBuH4mNZcp9z/VAVo53BZgcgkzWMZticl+2EEKIPCVhR0OZej3no65x9EoYp6Mucv5GGJfiwriaeJHotDBu6S9jn56JZ6IaYDwTwSsRmibCS1nbCRZ4xVnhmaRQIvXe27lTgCvqby0gwc2BC25liHTzIcHDDZ2PPXZeCu7FY/F3vkZN+xU4W/+GpS4j92/C2u3+kRd73/uDjbXcyiSEEEIbZhN2Jk+ezDfffENkZCQ1atTg559/pl69eprW9OuvCqevRnMl/iLXUsK4kXmRWOUC1vozuCoXKaG/imdKBl6JanCpnwAvJGIUbpyy8osFYJfDo7geSqYZtvV2kObkQIarHXoPOyzcFWyckrG2isVJl0R1jlGdY48u3tbjvktH94/GeIOVff58eEIIIUQeMYuw8/fffzNixAimTp1K/fr1+eGHH2jTpg2nT5/G0/MBq/gWgMQlrjyXEY93JpTQq7nEVQdWNoA9YHvnVw/AH+MQY5t9jmIPOpvcvaaaiZKAHNa30VnC3ZN6cxqRsfdRz7Gwfur3L4QQQpgCnaIoD76Ht5CoX78+devW5ZdffgFAr9fj5+fHW2+9xUcffXTf+ampqaSmZq8pExcXh5+fH7Gxsbjk4RK46T9bYF08jz9enZV6ScjKGayd1F+tnO7sc8r+vbXLXXcq3bmsJJN6hRBCmJG4uDhcXV0f+fO70I/spKWlcfDgQUaNGmXYZ2FhQXBwMKGhoTl+zcSJExk3bly+12bh4oWiv4lO5wCWDmoAsXMFe3ewcck5rNwbWoz2OYNlLod4hBBCCAGYQdi5fv06mZmZeHl5Ge338vLi1KlTOX7NqFGjGDFihGE7a2Qnr1n2i5A7i4QQQgiNFfqw8yRsbW2xtbXN/xeSoCOEEEJozkLrAp5WiRIlsLS0JOqeNgZRUVF4e3trVJUQQgghTEWhDzs2NjbUrl2bkJAQwz69Xk9ISAhBQUEaViaEEEIIU2AWl7FGjBhB//79qVOnDvXq1eOHH34gMTGRgQMHal2aEEIIITRmFmGnR48exMTE8NlnnxEZGUnNmjVZt27dfZOWhRBCCFH0mMU6O08rt/fpCyGEEMJ05Pbnd6GfsyOEEEII8TASdoQQQghh1iTsCCGEEMKsSdgRQgghhFmTsCOEEEIIsyZhRwghhBBmTcKOEEIIIcyahB0hhBBCmDWzWEH5aWWtqxgXF6dxJUIIIYTIrayf249aH1nCDhAfHw+An5+fxpUIIYQQ4nHFx8fj6ur6wOPSLgK1S3pERATOzs7odDqty9FMXFwcfn5+XL58WdpmPIB8Ro8mn1HuyOf0aPIZPVpR/4wURSE+Ph5fX18sLB48M0dGdgALCwtKlSqldRkmw8XFpUj+o3kc8hk9mnxGuSOf06PJZ/RoRfkzetiIThaZoCyEEEIIsyZhRwghhBBmTcKOMLC1tWXMmDHY2tpqXYrJks/o0eQzyh35nB5NPqNHk88od2SCshBCCCHMmozsCCGEEMKsSdgRQgghhFmTsCOEEEIIsyZhRwghhBBmTcJOIbZ9+3Y6duyIr68vOp2O5cuXGx1XFIXPPvsMHx8f7O3tCQ4O5uzZs0bn3Lx5k969e+Pi4oKbmxuDBg0iISHB6JwjR47QpEkT7Ozs8PPzY9KkSffVsmjRIipWrIidnR3VqlVjzZo1ef5+n8TEiROpW7cuzs7OeHp60rlzZ06fPm10TkpKCkOHDqV48eI4OTnRtWtXoqKijM4JDw+nffv2ODg44OnpyQcffEBGRobROVu3buXZZ5/F1taWcuXKMXPmzPvqmTx5MqVLl8bOzo769euzb9++PH/Pj2vKlClUr17dsChZUFAQa9euNRwv6p/Pg3z11VfodDqGDx9u2FfUP6uxY8ei0+mMHhUrVjQcL+qfz92uXr1Knz59KF68OPb29lSrVo0DBw4Yjsv37zymiEJrzZo1yieffKIsXbpUAZRly5YZHf/qq68UV1dXZfny5cp///2nvPDCC0pgYKCSnJxsOKdt27ZKjRo1lD179ig7duxQypUrp/Tq1ctwPDY2VvHy8lJ69+6tHDt2TJk/f75ib2+v/Pbbb4Zzdu3apVhaWiqTJk1STpw4oYwePVqxtrZWjh49mu+fwaO0adNGmTFjhnLs2DHl8OHDyvPPP6/4+/srCQkJhnOGDBmi+Pn5KSEhIcqBAweUBg0aKA0bNjQcz8jIUKpWraoEBwcrhw4dUtasWaOUKFFCGTVqlOGcCxcuKA4ODsqIESOUEydOKD///LNiaWmprFu3znDOggULFBsbG2X69OnK8ePHlcGDBytubm5KVFRUwXwYD/DPP/8oq1evVs6cOaOcPn1a+fjjjxVra2vl2LFjiqLI55OTffv2KaVLl1aqV6+uvPPOO4b9Rf2zGjNmjFKlShXl2rVrhkdMTIzheFH/fLLcvHlTCQgIUAYMGKDs3btXuXDhgrJ+/Xrl3LlzhnPk+3fekrBjJu4NO3q9XvH29la++eYbw77bt28rtra2yvz58xVFUZQTJ04ogLJ//37DOWvXrlV0Op1y9epVRVEU5ddff1WKFSumpKamGs4ZOXKkUqFCBcN29+7dlfbt2xvVU79+feX111/P0/eYF6KjoxVA2bZtm6Io6mdibW2tLFq0yHDOyZMnFUAJDQ1VFEUNlRYWFkpkZKThnClTpiguLi6Gz+XDDz9UqlSpYvRaPXr0UNq0aWPYrlevnjJ06FDDdmZmpuLr66tMnDgx79/oUypWrJjy559/yueTg/j4eKV8+fLKxo0bleeee84QduSzUsNOjRo1cjwmn0+2kSNHKo0bN37gcfn+nffkMpaZCgsLIzIykuDgYMM+V1dX6tevT2hoKAChoaG4ublRp04dwznBwcFYWFiwd+9ewzlNmzbFxsbGcE6bNm04ffo0t27dMpxz9+tknZP1OqYkNjYWAHd3dwAOHjxIenq6Uf0VK1bE39/f6HOqVq0aXl5ehnPatGlDXFwcx48fN5zzsM8gLS2NgwcPGp1jYWFBcHCwSX1OmZmZLFiwgMTERIKCguTzycHQoUNp3779fe9HPivV2bNn8fX1pUyZMvTu3Zvw8HBAPp+7/fPPP9SpU4eXXnoJT09PatWqxR9//GE4Lt+/856EHTMVGRkJYPRNI2s761hkZCSenp5Gx62srHB3dzc6J6fnuPs1HnRO1nFTodfrGT58OI0aNaJq1aqAWruNjQ1ubm5G5977OT3pZxAXF0dycjLXr18nMzPTZD+no0eP4uTkhK2tLUOGDGHZsmVUrlxZPp97LFiwgH///ZeJEyfed0w+K6hfvz4zZ85k3bp1TJkyhbCwMJo0aUJ8fLx8Pne5cOECU6ZMoXz58qxfv5433niDt99+m1mzZgHy/Ts/SNdzUWQMHTqUY8eOsXPnTq1LMTkVKlTg8OHDxMbGsnjxYvr378+2bdu0LsukXL58mXfeeYeNGzdiZ2endTkmqV27dobfV69enfr16xMQEMDChQuxt7fXsDLTotfrqVOnDhMmTACgVq1aHDt2jKlTp9K/f3+NqzNPMrJjpry9vQHuu9MhKirKcMzb25vo6Gij4xkZGdy8edPonJye4+7XeNA5WcdNwbBhw1i1ahVbtmyhVKlShv3e3t6kpaVx+/Zto/Pv/Zye9DNwcXHB3t6eEiVKYGlpabKfk42NDeXKlaN27dpMnDiRGjVq8OOPP8rnc5eDBw8SHR3Ns88+i5WVFVZWVmzbto2ffvoJKysrvLy85LO6h5ubG8888wznzp2Tv0t38fHxoXLlykb7KlWqZLjkJ9+/856EHTMVGBiIt7c3ISEhhn1xcXHs3buXoKAgAIKCgrh9+zYHDx40nLN582b0ej3169c3nLN9+3bS09MN52zcuJEKFSpQrFgxwzl3v07WOVmvoyVFURg2bBjLli1j8+bNBAYGGh2vXbs21tbWRvWfPn2a8PBwo8/p6NGjRt9YNm7ciIuLi+Eb1qM+AxsbG2rXrm10jl6vJyQkxCQ+p3vp9XpSU1Pl87lLy5YtOXr0KIcPHzY86tSpQ+/evQ2/l8/KWEJCAufPn8fHx0f+Lt2lUaNG9y2BcebMGQICAgD5/p0vtJ4hLZ5cfHy8cujQIeXQoUMKoHz33XfKoUOHlEuXLimKot666ObmpqxYsUI5cuSI0qlTpxxvXaxVq5ayd+9eZefOnUr58uWNbl28ffu24uXlpfTt21c5duyYsmDBAsXBweG+WxetrKyUb7/9Vjl58qQyZswYk7l18Y033lBcXV2VrVu3Gt0Om5SUZDhnyJAhir+/v7J582blwIEDSlBQkBIUFGQ4nnU7bOvWrZXDhw8r69atUzw8PHK8HfaDDz5QTp48qUyePDnH22FtbW2VmTNnKidOnFBee+01xc3NzejOEy189NFHyrZt25SwsDDlyJEjykcffaTodDplw4YNiqLI5/Mwd9+NpSjyWb333nvK1q1blbCwMGXXrl1KcHCwUqJECSU6OlpRFPl8suzbt0+xsrJSvvzyS+Xs2bPKX3/9pTg4OChz5841nCPfv/OWhJ1CbMuWLQpw36N///6Koqi3L3766aeKl5eXYmtrq7Rs2VI5ffq00XPcuHFD6dWrl+Lk5KS4uLgoAwcOVOLj443O+e+//5TGjRsrtra2SsmSJZWvvvrqvloWLlyoPPPMM4qNjY1SpUoVZfXq1fn2vh9HTp8PoMyYMcNwTnJysvLmm28qxYoVUxwcHJQuXboo165dM3qeixcvKu3atVPs7e2VEiVKKO+9956Snp5udM6WLVuUmjVrKjY2NkqZMmWMXiPLzz//rPj7+ys2NjZKvXr1lD179uTH234sr7zyihIQEKDY2NgoHh4eSsuWLQ1BR1Hk83mYe8NOUf+sevToofj4+Cg2NjZKyZIllR49ehitHVPUP5+7rVy5Uqlatapia2urVKxYUfn999+Njsv377ylUxRF0WZMSQghhBAi/8mcHSGEEEKYNQk7QgghhDBrEnaEEEIIYdYk7AghhBDCrEnYEUIIIYRZk7AjhBBCCLMmYUcIIYQQZk3CjhBCCCHMmoQdIYQQQpg1CTtCCCGEMGsSdoQQQghh1qy0LkAIIfJDs2bNqF69OnZ2dvz555/Y2NgwZMgQxo4dq3VpQogCJiM7QgizNWvWLBwdHdm7dy+TJk1i/PjxbNy4UeuyhBAFTLqeCyHMUrNmzcjMzGTHjh2GffXq1aNFixZ89dVXGlYmhChoMrIjhDBb1atXN9r28fEhOjpao2qEEFqRsCOEMFvW1tZG2zqdDr1er1E1QgitSNgRQgghhFmTsCOEEEIIsyZhRwghhBBmTe7GEkIIIYRZk5EdIYQQQpg1CTtCCCGEMGsSdoQQQghh1iTsCCGEEMKsSdgRQgghhFmTsCOEEEIIsyZhRwghhBBmTcKOEEIIIcyahB0hhBBCmDUJO0IIIYQwaxJ2hBBCCGHW/g9O3DZe0uwBggAAAABJRU5ErkJggg==",
      "text/plain": [
       "<Figure size 640x480 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "forward:\n",
      "         n        NSA  Triton-FA2         FA2         FA3\n",
      "0   4096.0   1.636043    1.237447    0.854760    0.433516\n",
      "1   8192.0   3.369944    4.586613    3.172062    1.712960\n",
      "2  16384.0   7.667904   17.924274   12.195124    6.874225\n",
      "3  32768.0  19.261448   73.122749   47.660912   26.929739\n",
      "4  65536.0  54.878178  294.555847  191.237671  106.627266\n"
     ]
    }
   ],
   "source": [
    "torch.cuda.empty_cache()\n",
    "@triton.testing.perf_report(\n",
    "    triton.testing.Benchmark(\n",
    "        x_names=['n'],  # argument names to use as an x-axis for the plot\n",
    "        x_vals=[4096 * 2**i for i in range(0, 5)],  # different possible values for `x_name`\n",
    "        line_arg='provider',  # argument name whose value corresponds to a different line in the plot\n",
    "        line_vals=['NSA', 'Triton-FA2', 'FA2', 'FA3'],  # possible values for `line_arg``\n",
    "        line_names=[\n",
    "            \"NSA\",\n",
    "            \"Triton-FA2\",\n",
    "            \"FA2\",\n",
    "            \"FA3\",\n",
    "        ],  # label name for the lines\n",
    "        styles=[('blue', '-'), ('green', '-'), ('red', '-'), ('orange', '-')],  # line styles\n",
    "        ylabel=\"ms\",  # label name for the y-axis\n",
    "        plot_name=\"forward\",  # name for the plot. Used also as a file name for saving the plot.\n",
    "        args={'b':1, 'qh':64, 'kh':4, 'd':128, 'vd':128, 'stride':16, 'kernel_size':32, 'select_size': 64, 'top_n':16,'window_size':512},  # values for function arguments not in `x_names` and `y_name`\n",
    "    ))\n",
    "def benchmark(b, qh, kh, n, d, vd, stride, kernel_size, select_size, top_n, window_size, provider):\n",
    "    device = 'cuda'\n",
    "    dtype = torch.bfloat16\n",
    "    device = 'cuda'\n",
    "    dtype = torch.bfloat16\n",
    "    q = torch.randn(b, n, qh, d, device=device, dtype=dtype)\n",
    "    k = torch.randn(b, n, kh, d, device=device, dtype=dtype)\n",
    "    v = torch.randn(b, n, kh, vd, device=device, dtype=dtype)\n",
    "    stream = torch.cuda.Stream()\n",
    "    torch.cuda.set_stream(stream)\n",
    "    if provider == 'NSA':\n",
    "        nsa = NsaAttention(d, vd, kernel_size, stride, select_size, top_n, window_size).to(device).to(dtype)\n",
    "        ms = triton.testing.do_bench(lambda: nsa(q, k, v))\n",
    "    if provider == 'Triton-FA2':\n",
    "        ms = triton.testing.do_bench(lambda: triton_fa2(q, k, v))\n",
    "    if provider == 'FA2':\n",
    "        if not HAVE_FA2:\n",
    "            return 0\n",
    "        ms = triton.testing.do_bench(lambda: fa2(q, k, v, causal=True))\n",
    "    if provider == 'FA3':\n",
    "        if not HAVE_FA3:\n",
    "            return 0\n",
    "        ms = triton.testing.do_bench(lambda: fa3(q, k, v, causal=True))\n",
    "    return ms\n",
    "benchmark.run(show_plots=True, print_data=True)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Triton autotuning for function _dq_kernel finished after 21.66s; best config selected: BLOCK_SIZE_N: 128, BLOCK_SIZE_M: 128, num_warps: 8, num_ctas: 1, num_stages: 2, maxnreg: None;\n",
      "Triton autotuning for function _dq_kernel finished after 2.67s; best config selected: BLOCK_SIZE_N: 128, BLOCK_SIZE_M: 128, num_warps: 8, num_ctas: 1, num_stages: 2, maxnreg: None;\n",
      "Triton autotuning for function _dq_kernel finished after 4.97s; best config selected: BLOCK_SIZE_N: 128, BLOCK_SIZE_M: 128, num_warps: 8, num_ctas: 1, num_stages: 2, maxnreg: None;\n",
      "Triton autotuning for function _dq_kernel finished after 16.79s; best config selected: BLOCK_SIZE_N: 128, BLOCK_SIZE_M: 128, num_warps: 8, num_ctas: 1, num_stages: 2, maxnreg: None;\n",
      "Triton autotuning for function _dq_kernel finished after 68.04s; best config selected: BLOCK_SIZE_N: 128, BLOCK_SIZE_M: 128, num_warps: 8, num_ctas: 1, num_stages: 2, maxnreg: None;\n"
     ]
    },
    {
     "data": {
      "image/png": "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",
      "text/plain": [
       "<Figure size 640x480 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "backward:\n",
      "         n         NSA  Triton-FA2         FA2         FA3\n",
      "0   4096.0    4.231524    4.086307    2.508782    1.380329\n",
      "1   8192.0    8.861718   15.639690    8.953718    4.971749\n",
      "2  16384.0   19.791449   61.520321   33.811104   18.827488\n",
      "3  32768.0   46.977791  247.759003  135.482559   76.256958\n",
      "4  65536.0  123.787613  987.546387  538.496399  294.824921\n"
     ]
    }
   ],
   "source": [
    "torch.cuda.empty_cache()\n",
    "@triton.testing.perf_report(\n",
    "    triton.testing.Benchmark(\n",
    "        x_names=['n'],  # argument names to use as an x-axis for the plot\n",
    "        x_vals=[4096 * 2**i for i in range(0, 5)],  # different possible values for `x_name`\n",
    "        line_arg='provider',  # argument name whose value corresponds to a different line in the plot\n",
    "        line_vals=['NSA', 'Triton-FA2', 'FA2', 'FA3'],  # possible values for `line_arg``\n",
    "        line_names=[\n",
    "            \"NSA\",\n",
    "            \"Triton-FA2\",\n",
    "            \"FA2\",\n",
    "            \"FA3\",\n",
    "        ],  # label name for the lines\n",
    "        styles=[('blue', '-'), ('green', '-'), ('red', '-'), ('orange', '-')],  # line styles\n",
    "        ylabel=\"ms\",  # label name for the y-axis\n",
    "        plot_name=\"backward\",  # name for the plot. Used also as a file name for saving the plot.\n",
    "        args={'b':1, 'qh':64, 'kh':4, 'd':128, 'vd':128, 'stride':16, 'kernel_size':32, 'select_size': 64, 'top_n':16,'window_size':512},  # values for function arguments not in `x_names` and `y_name`\n",
    "    ))\n",
    "def benchmark(b, qh, kh, n, d, vd, stride, kernel_size, select_size, top_n, window_size, provider):\n",
    "    device = 'cuda'\n",
    "    dtype = torch.bfloat16\n",
    "    q = torch.randn(b, n, qh, d, device=device, dtype=dtype)\n",
    "    k = torch.randn(b, n, kh, d, device=device, dtype=dtype)\n",
    "    v = torch.randn(b, n, kh, vd, device=device, dtype=dtype)\n",
    "    q.requires_grad_(True)\n",
    "    k.requires_grad_(True)\n",
    "    v.requires_grad_(True)\n",
    "    dy = torch.randn(b, n, qh, vd, device=device, dtype=dtype)\n",
    "    stream = torch.cuda.Stream()\n",
    "    torch.cuda.set_stream(stream)\n",
    "    if provider == 'NSA':\n",
    "        nsa = NsaAttention(d, vd, kernel_size, stride, select_size, top_n, window_size).to(device).to(dtype)\n",
    "        # inplace用于测试，bwd_ind会被原地修改，改为不原地修改\n",
    "        y = nsa(q, k, v, inplace=False)\n",
    "        dy = torch.randn_like(y)\n",
    "        ms = triton.testing.do_bench(lambda: y.backward(dy, retain_graph=True), grad_to_none=[q,k,v])\n",
    "    if provider == 'Triton-FA2':\n",
    "        y, _ = triton_fa2(q, k, v)\n",
    "        ms = triton.testing.do_bench(lambda: y.backward(dy, retain_graph=True), grad_to_none=[q,k,v])\n",
    "    if provider == 'FA2':\n",
    "        if not HAVE_FA2:\n",
    "            return 0\n",
    "        y = fa2(q, k, v, causal=True)\n",
    "        ms = triton.testing.do_bench(lambda: y.backward(dy, retain_graph=True), grad_to_none=[q,k,v])\n",
    "    if provider == 'FA3':\n",
    "        if not HAVE_FA3:\n",
    "            return 0\n",
    "        y, _ = fa3(q, k, v, causal=True)\n",
    "        ms = triton.testing.do_bench(lambda: y.backward(dy, retain_graph=True), grad_to_none=[q,k,v])\n",
    "    return ms\n",
    "benchmark.run(show_plots=True, print_data=True)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.12.8"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
